#include <cstdio>
#include <gtest/gtest.h>
#include "pipeline_task.hpp"
#include "scheduler.hpp"
#include <thread>
#include <arrow/api.h>
#include <memory>
#include <string>
#include "logical_type.hpp"
#include "rc.hpp"
#include "numa_help.hpp"
#include "catalog.hpp"
#include "physical_table_scan.hpp"
#include "physical_filter.hpp"
#include "physical_project.hpp"
#include "create_statement.hpp"
#include "postgres_parser.hpp"
#include "binder.h"
#include "spdlog/fmt/bundled/core.h"
#include "planner.hpp"
#include "nest_loop_join_plan.h"
#include "statement_type.hpp"
#include "select_statement.hpp"
#include "physical_radix_join.hpp"
#include "physical_hash_aggregation.hpp"
#include "pipeline_group_execute.hpp"
#include "pipe.h"
#include "expression_executor.hpp"
#include "expression.hpp"
#include "arrow_help.hpp"
#include <spdlog/spdlog.h>
#include "like.hpp"
#include "string_functions.hpp"
#include "physical_result_collector.hpp"
#include "physical_order.hpp"
#include "numeric.hpp"
#include "bound_project_function_expression.hpp"
#include "physical_hash_join.hpp"
#include "physical_nested_loop_join.hpp"
#include <fstream>
#include <sstream>
#include "bound_in_expression.hpp"
#include "bound_case_expression.hpp"
#include "physical_hash_aggregation_with_multifield.hpp"
#include "date.hpp"

#define CHUNK_SZIE 4096

std::mutex mtx;
std::condition_variable cv;
bool importFinish = false;
std::string fileDir = "/home/cwl/data/experiment_0.1";
std::string fileDir2 = "/home/cwl/data/experiment_1/2thread";
std::string fileDir4 = "/home/cwl/data/experiment_0.1/thread4";
std::string fileDir5 = "/home/cwl/data/experiment_0.1/thread4";

using namespace DaseX;

void ImportDataFromNation(std::shared_ptr<Table> &table, int partition_idx, std::string &fileName) {
    arrow::Status ok;
    // 构建Schema
    std::shared_ptr<arrow::Field> n_nationkey, n_name, n_regionkey, n_comment;
    std::shared_ptr<arrow::Schema> schema;
    n_nationkey = arrow::field("n_nationkey", arrow::int32());
    n_name = arrow::field("n_name", arrow::utf8());
    n_regionkey = arrow::field("n_regionkey", arrow::int32());
    n_comment = arrow::field("n_comment", arrow::utf8());
    schema = arrow::schema({n_nationkey, n_name, n_regionkey, n_comment});
    // 读取文件数据
    std::vector<int> nationkey;
    std::vector<std::string> name;
    std::vector<int> regionkey;
    std::vector<std::string> comment;
    std::ifstream infile(fileName);
    std::string line;
    if (!infile.is_open()) {
        std::cerr << "无法打开文件" << std::endl;
        return;
    }
    int count = 0;
    int round = 0;
    while (std::getline(infile, line)) {
        std::istringstream iss(line);
        std::string part;
        std::vector<std::string> parts;
        while (std::getline(iss, part, '|')) {
            parts.emplace_back(part);
        }
        nationkey.push_back(std::stoi(parts[0]));
        name.push_back(parts[1]);
        regionkey.push_back(std::stoi(parts[2]));
        comment.push_back(parts[3]);
        count++;
        if(count == CHUNK_SZIE) {
            round++;
            std::shared_ptr<arrow::Array> nationkey_array;
            std::shared_ptr<arrow::Array> name_array;
            std::shared_ptr<arrow::Array> regionkey_array;
            std::shared_ptr<arrow::Array> comment_array;
            ok = DaseX::Util::AppendIntArray(nationkey_array, nationkey);
            ok = DaseX::Util::AppendStringArray(name_array, name);
            ok = DaseX::Util::AppendIntArray(regionkey_array, regionkey);
            ok = DaseX::Util::AppendStringArray(comment_array, comment);
            std::shared_ptr<arrow::RecordBatch> rbatch;
            rbatch = arrow::RecordBatch::Make(schema, CHUNK_SZIE, {nationkey_array, name_array, regionkey_array, comment_array});
            table->insert_data(rbatch, partition_idx);
            count = 0;
            // 清空向量
            nationkey.clear();
            name.clear();
            regionkey.clear();
            comment.clear();
        }
    }
    if(count != 0) {
        std::shared_ptr<arrow::Array> nationkey_array;
        std::shared_ptr<arrow::Array> name_array;
        std::shared_ptr<arrow::Array> regionkey_array;
        std::shared_ptr<arrow::Array> comment_array;
        ok = DaseX::Util::AppendIntArray(nationkey_array, nationkey);
        ok = DaseX::Util::AppendStringArray(name_array, name);
        ok = DaseX::Util::AppendIntArray(regionkey_array, regionkey);
        ok = DaseX::Util::AppendStringArray(comment_array, comment);
        std::shared_ptr<arrow::RecordBatch> rbatch;
        rbatch = arrow::RecordBatch::Make(schema, count, {nationkey_array, name_array, regionkey_array, comment_array});
        table->insert_data(rbatch, partition_idx);
    }
    spdlog::info("[{} : {}] The round is: {}, the final count is: {} .", __FILE__, __LINE__, round, count);
    infile.close();
    importFinish = true;
    cv.notify_all();
}

void ImportDataFromRegion(std::shared_ptr<Table> &table, int partition_idx, std::string &fileName) {
    arrow::Status ok;
    // 构建Schema
    std::shared_ptr<arrow::Field> r_regionkey, r_name, r_comment;
    std::shared_ptr<arrow::Schema> schema;
    r_regionkey = arrow::field("r_regionkey", arrow::int32());
    r_name = arrow::field("r_name", arrow::utf8());
    r_comment = arrow::field("r_comment", arrow::utf8());
    schema = arrow::schema({r_regionkey, r_name, r_comment});
    // 读取文件数据
    std::vector<int> regionkey;
    std::vector<std::string> name;
    std::vector<std::string> comment;
    std::ifstream infile(fileName);
    std::string line;
    if (!infile.is_open()) {
        std::cerr << "无法打开文件" << std::endl;
        return;
    }
    int count = 0;
    int round = 0;
    while (std::getline(infile, line)) {
        std::istringstream iss(line);
        std::string part;
        std::vector<std::string> parts;
        while (std::getline(iss, part, '|')) {
            parts.emplace_back(part);
        }
        regionkey.push_back(std::stoi(parts[0]));
        name.push_back(parts[1]);
        comment.push_back(parts[2]);
        count++;
        if(count == CHUNK_SZIE) {
            round++;
            std::shared_ptr<arrow::Array> regionkey_array;
            std::shared_ptr<arrow::Array> name_array;
            std::shared_ptr<arrow::Array> comment_array;
            ok = DaseX::Util::AppendIntArray(regionkey_array, regionkey);
            ok = DaseX::Util::AppendStringArray(name_array, name);
            ok = DaseX::Util::AppendStringArray(comment_array, comment);
            std::shared_ptr<arrow::RecordBatch> rbatch;
            rbatch = arrow::RecordBatch::Make(schema, CHUNK_SZIE, {regionkey_array, name_array, comment_array});
            table->insert_data(rbatch, partition_idx);
            count = 0;
            // 清空向量
            regionkey.clear();
            name.clear();
            comment.clear();
        }
    }
    if(count != 0) {
        std::shared_ptr<arrow::Array> regionkey_array;
        std::shared_ptr<arrow::Array> name_array;
        std::shared_ptr<arrow::Array> comment_array;
        ok = DaseX::Util::AppendIntArray(regionkey_array, regionkey);
        ok = DaseX::Util::AppendStringArray(name_array, name);
        ok = DaseX::Util::AppendStringArray(comment_array, comment);
        std::shared_ptr<arrow::RecordBatch> rbatch;
        rbatch = arrow::RecordBatch::Make(schema, count, {regionkey_array, name_array, comment_array});
        table->insert_data(rbatch, partition_idx);
    }
    spdlog::info("[{} : {}] The round is: {}, the final count is: {} .", __FILE__, __LINE__, round, count);
    infile.close();
    importFinish = true;
    cv.notify_all();
}

void ImportDataFromPart(std::shared_ptr<Table> &table, int partition_idx, std::string &fileName) {
    arrow::Status ok;
    // 构建Schema
    std::shared_ptr<arrow::Field> p_partkey, p_name, p_mfgr, p_brand, p_type, p_size, p_container, p_retailprice, p_comment;
    std::shared_ptr<arrow::Schema> schema;
    p_partkey = arrow::field("p_partkey", arrow::int32());
    p_name = arrow::field("p_name", arrow::utf8());
    p_mfgr = arrow::field("p_mfgr", arrow::utf8());
    p_brand = arrow::field("p_brand", arrow::utf8());
    p_type = arrow::field("p_type", arrow::utf8());
    p_size = arrow::field("p_size", arrow::int32());
    p_container = arrow::field("p_container", arrow::utf8());
    p_retailprice = arrow::field("p_retailprice", arrow::float32());
    p_comment = arrow::field("p_comment", arrow::utf8());
    schema = arrow::schema({p_partkey, p_name, p_mfgr, p_brand, p_type, p_size, p_container, p_retailprice, p_comment});
    // 读取文件数据
    std::vector<int> partkey;
    std::vector<std::string> name;
    std::vector<std::string> mfgr;
    std::vector<std::string> brand;
    std::vector<std::string> type;
    std::vector<int> size;
    std::vector<std::string> container;
    std::vector<float> retailprice;
    std::vector<std::string> comment;
    std::ifstream infile(fileName);
    std::string line;
    if (!infile.is_open()) {
        std::cerr << "无法打开文件" << std::endl;
        return;
    }
    int count = 0;
    int round = 0;
    while (std::getline(infile, line)) {
        std::istringstream iss(line);
        std::string part;
        std::vector<std::string> parts;
        while (std::getline(iss, part, '|')) {
            parts.emplace_back(part);
        }
        partkey.push_back(std::stoi(parts[0]));
        name.push_back(parts[1]);
        mfgr.push_back(parts[2]);
        brand.push_back(parts[3]);
        type.push_back(parts[4]);
        size.push_back(std::stoi(parts[5]));
        container.push_back(parts[6]);
        retailprice.push_back(std::stof(parts[7]));
        comment.push_back(parts[8]);
        count++;
        if(count == CHUNK_SZIE) {
            round++;
            std::shared_ptr<arrow::Array> partkey_array;
            std::shared_ptr<arrow::Array> name_array;
            std::shared_ptr<arrow::Array> mfgr_array;
            std::shared_ptr<arrow::Array> brand_array;
            std::shared_ptr<arrow::Array> type_array;
            std::shared_ptr<arrow::Array> size_array;
            std::shared_ptr<arrow::Array> container_array;
            std::shared_ptr<arrow::Array> retailprice_array;
            std::shared_ptr<arrow::Array> comment_array;
            ok = DaseX::Util::AppendIntArray(partkey_array, partkey);
            ok = DaseX::Util::AppendStringArray(name_array, name);
            ok = DaseX::Util::AppendStringArray(mfgr_array, mfgr);
            ok = DaseX::Util::AppendStringArray(brand_array, brand);
            ok = DaseX::Util::AppendStringArray(type_array, type);
            ok = DaseX::Util::AppendIntArray(size_array, size);
            ok = DaseX::Util::AppendStringArray(container_array, container);
            ok = DaseX::Util::AppendFloatArray(retailprice_array, retailprice);
            ok = DaseX::Util::AppendStringArray(comment_array, comment);
            std::shared_ptr<arrow::RecordBatch> rbatch;
            rbatch = arrow::RecordBatch::Make(schema, CHUNK_SZIE, {partkey_array, name_array, mfgr_array, brand_array, type_array, size_array, container_array, retailprice_array, comment_array});
            table->insert_data(rbatch, partition_idx);
            count = 0;
            // 清空向量
            partkey.clear();
            name.clear();
            mfgr.clear();
            brand.clear();
            type.clear();
            size.clear();
            container.clear();
            retailprice.clear();
            comment.clear();
        }
    }
    if(count != 0) {
        std::shared_ptr<arrow::Array> partkey_array;
        std::shared_ptr<arrow::Array> name_array;
        std::shared_ptr<arrow::Array> mfgr_array;
        std::shared_ptr<arrow::Array> brand_array;
        std::shared_ptr<arrow::Array> type_array;
        std::shared_ptr<arrow::Array> size_array;
        std::shared_ptr<arrow::Array> container_array;
        std::shared_ptr<arrow::Array> retailprice_array;
        std::shared_ptr<arrow::Array> comment_array;
        ok = DaseX::Util::AppendIntArray(partkey_array, partkey);
        ok = DaseX::Util::AppendStringArray(name_array, name);
        ok = DaseX::Util::AppendStringArray(mfgr_array, mfgr);
        ok = DaseX::Util::AppendStringArray(brand_array, brand);
        ok = DaseX::Util::AppendStringArray(type_array, type);
        ok = DaseX::Util::AppendIntArray(size_array, size);
        ok = DaseX::Util::AppendStringArray(container_array, container);
        ok = DaseX::Util::AppendFloatArray(retailprice_array, retailprice);
        ok = DaseX::Util::AppendStringArray(comment_array, comment);
        std::shared_ptr<arrow::RecordBatch> rbatch;
        rbatch = arrow::RecordBatch::Make(schema, count, {partkey_array, name_array, mfgr_array, brand_array, type_array, size_array, container_array, retailprice_array, comment_array});
        table->insert_data(rbatch, partition_idx);
    }
    spdlog::info("[{} : {}] The round is: {}, the final count is: {} .", __FILE__, __LINE__, round, count);
    infile.close();
    importFinish = true;
    cv.notify_all();
}

void ImportDataFromSupplier(std::shared_ptr<Table> &table, int partition_idx, std::string &fileName) {
    arrow::Status ok;
    // 构建Schema
    std::shared_ptr<arrow::Field> s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment;
    std::shared_ptr<arrow::Schema> schema;
    s_suppkey = arrow::field("s_suppkey", arrow::int32());
    s_name = arrow::field("s_name", arrow::utf8());
    s_address = arrow::field("s_address", arrow::utf8());
    s_nationkey = arrow::field("s_nationkey", arrow::int32());
    s_phone = arrow::field("s_phone", arrow::utf8());
    s_acctbal = arrow::field("s_acctbal", arrow::float32());
    s_comment = arrow::field("s_comment", arrow::utf8());
    schema = arrow::schema({s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment});
    // 读取文件数据
    std::vector<int> suppkey;
    std::vector<std::string> name;
    std::vector<std::string> address;
    std::vector<int> nationkey;
    std::vector<std::string> phone;
    std::vector<float> acctbal;
    std::vector<std::string> comment;
    std::ifstream infile(fileName);
    std::string line;
    if (!infile.is_open()) {
        std::cerr << "无法打开文件" << std::endl;
        return;
    }
    int count = 0;
    int round = 0;
    while (std::getline(infile, line)) {
        std::istringstream iss(line);
        std::string part;
        std::vector<std::string> parts;
        while (std::getline(iss, part, '|')) {
            parts.emplace_back(part);
        }
        suppkey.push_back(std::stoi(parts[0]));
        name.push_back(parts[1]);
        address.push_back(parts[2]);
        nationkey.push_back(std::stoi(parts[3]));
        phone.push_back(parts[4]);
        acctbal.push_back(std::stof(parts[5]));
        comment.push_back(parts[6]);
        count++;
        if(count == CHUNK_SZIE) {
            round++;
            std::shared_ptr<arrow::Array> suppkey_array;
            std::shared_ptr<arrow::Array> name_array;
            std::shared_ptr<arrow::Array> address_array;
            std::shared_ptr<arrow::Array> nationkey_array;
            std::shared_ptr<arrow::Array> phone_array;
            std::shared_ptr<arrow::Array> acctbal_array;
            std::shared_ptr<arrow::Array> comment_array;
            ok = DaseX::Util::AppendIntArray(suppkey_array, suppkey);
            ok = DaseX::Util::AppendStringArray(name_array, name);
            ok = DaseX::Util::AppendStringArray(address_array, address);
            ok = DaseX::Util::AppendIntArray(nationkey_array, nationkey);
            ok = DaseX::Util::AppendStringArray(phone_array, phone);
            ok = DaseX::Util::AppendFloatArray(acctbal_array, acctbal);
            ok = DaseX::Util::AppendStringArray(comment_array, comment);
            std::shared_ptr<arrow::RecordBatch> rbatch;
            rbatch = arrow::RecordBatch::Make(schema, CHUNK_SZIE, {suppkey_array, name_array, address_array, nationkey_array, phone_array, acctbal_array, comment_array});
            table->insert_data(rbatch, partition_idx);
            count = 0;
            // 清空向量
            suppkey.clear();
            name.clear();
            address.clear();
            nationkey.clear();
            phone.clear();
            acctbal.clear();
            comment.clear();
        }
    }
    if(count != 0) {
        std::shared_ptr<arrow::Array> suppkey_array;
        std::shared_ptr<arrow::Array> name_array;
        std::shared_ptr<arrow::Array> address_array;
        std::shared_ptr<arrow::Array> nationkey_array;
        std::shared_ptr<arrow::Array> phone_array;
        std::shared_ptr<arrow::Array> acctbal_array;
        std::shared_ptr<arrow::Array> comment_array;
        ok = DaseX::Util::AppendIntArray(suppkey_array, suppkey);
        ok = DaseX::Util::AppendStringArray(name_array, name);
        ok = DaseX::Util::AppendStringArray(address_array, address);
        ok = DaseX::Util::AppendIntArray(nationkey_array, nationkey);
        ok = DaseX::Util::AppendStringArray(phone_array, phone);
        ok = DaseX::Util::AppendFloatArray(acctbal_array, acctbal);
        ok = DaseX::Util::AppendStringArray(comment_array, comment);
        std::shared_ptr<arrow::RecordBatch> rbatch;
        rbatch = arrow::RecordBatch::Make(schema, count, {suppkey_array, name_array, address_array, nationkey_array, phone_array, acctbal_array, comment_array});
        table->insert_data(rbatch, partition_idx);
    }
    spdlog::info("[{} : {}] The round is: {}, the final count is: {} .", __FILE__, __LINE__, round, count);
    infile.close();
    importFinish = true;
    cv.notify_all();
}

void ImportDataFromPartsupp(std::shared_ptr<Table> &table, int partition_idx, std::string &fileName) {
    arrow::Status ok;
    // 构建Schema
    std::shared_ptr<arrow::Field> ps_partkey, ps_suppkey, ps_availqty, ps_supplycost, ps_comment;
    std::shared_ptr<arrow::Schema> schema;
    ps_partkey = arrow::field("ps_partkey", arrow::int32());
    ps_suppkey = arrow::field("ps_suppkey", arrow::int32());
    ps_availqty = arrow::field("ps_availqty", arrow::int32());
    ps_supplycost = arrow::field("ps_supplycost", arrow::float32());
    ps_comment = arrow::field("ps_comment", arrow::utf8());
    schema = arrow::schema({ps_partkey, ps_suppkey, ps_availqty, ps_supplycost, ps_comment});
    // 读取文件数据
    std::vector<int> partkey;
    std::vector<int> suppkey;
    std::vector<int> availqty;
    std::vector<float> supplycost;
    std::vector<std::string> comment;
    std::ifstream infile(fileName);
    std::string line;
    if (!infile.is_open()) {
        std::cerr << "无法打开文件" << std::endl;
        return;
    }
    int count = 0;
    int round = 0;
    while (std::getline(infile, line)) {
        std::istringstream iss(line);
        std::string part;
        std::vector<std::string> parts;
        while (std::getline(iss, part, '|')) {
            parts.emplace_back(part);
        }
        partkey.push_back(std::stoi(parts[0]));
        suppkey.push_back(std::stoi(parts[1]));
        availqty.push_back(std::stoi(parts[2]));
        supplycost.push_back(std::stof(parts[3]));
        comment.push_back(parts[4]);
        count++;
        if(count == CHUNK_SZIE) {
            round++;
            std::shared_ptr<arrow::Array> partkey_array;
            std::shared_ptr<arrow::Array> suppkey_array;
            std::shared_ptr<arrow::Array> availqty_array;
            std::shared_ptr<arrow::Array> supplycost_array;
            std::shared_ptr<arrow::Array> comment_array;
            ok = DaseX::Util::AppendIntArray(partkey_array, partkey);
            ok = DaseX::Util::AppendIntArray(suppkey_array, suppkey);
            ok = DaseX::Util::AppendIntArray(availqty_array, availqty);
            ok = DaseX::Util::AppendFloatArray(supplycost_array, supplycost);
            ok = DaseX::Util::AppendStringArray(comment_array, comment);
            std::shared_ptr<arrow::RecordBatch> rbatch;
            rbatch = arrow::RecordBatch::Make(schema, CHUNK_SZIE, {partkey_array, suppkey_array, availqty_array, supplycost_array, comment_array});
            table->insert_data(rbatch, partition_idx);
            count = 0;
            // 清空向量
            partkey.clear();
            suppkey.clear();
            availqty.clear();
            supplycost.clear();
            comment.clear();
        }
    }
    if(count != 0) {
        std::shared_ptr<arrow::Array> partkey_array;
        std::shared_ptr<arrow::Array> suppkey_array;
        std::shared_ptr<arrow::Array> availqty_array;
        std::shared_ptr<arrow::Array> supplycost_array;
        std::shared_ptr<arrow::Array> comment_array;
        ok = DaseX::Util::AppendIntArray(partkey_array, partkey);
        ok = DaseX::Util::AppendIntArray(suppkey_array, suppkey);
        ok = DaseX::Util::AppendIntArray(availqty_array, availqty);
        ok = DaseX::Util::AppendFloatArray(supplycost_array, supplycost);
        ok = DaseX::Util::AppendStringArray(comment_array, comment);
        std::shared_ptr<arrow::RecordBatch> rbatch;
        rbatch = arrow::RecordBatch::Make(schema, count, {partkey_array, suppkey_array, availqty_array, supplycost_array, comment_array});
        table->insert_data(rbatch, partition_idx);
    }
    spdlog::info("[{} : {}] The round is: {}, the final count is: {} .", __FILE__, __LINE__, round, count);
    infile.close();
    importFinish = true;
    cv.notify_all();
}

void ImportDataFromCustomer(std::shared_ptr<Table> &table, int partition_idx, std::string &fileName) {
    arrow::Status ok;
    // 构建Schema
    std::shared_ptr<arrow::Field> c_custkey, c_name, c_address, c_nationkey, c_phone, c_acctbal, c_mktsegment, c_comment;
    std::shared_ptr<arrow::Schema> schema;
    c_custkey = arrow::field("c_custkey", arrow::int32());
    c_name = arrow::field("c_name", arrow::utf8());
    c_address = arrow::field("c_address", arrow::utf8());
    c_nationkey = arrow::field("c_nationkey", arrow::int32());
    c_phone = arrow::field("c_phone", arrow::utf8());
    c_acctbal = arrow::field("c_acctbal", arrow::float32());
    c_mktsegment = arrow::field("c_mktsegment", arrow::utf8());
    c_comment = arrow::field("c_comment", arrow::utf8());
    schema = arrow::schema({c_custkey, c_name, c_address, c_nationkey, c_phone, c_acctbal, c_mktsegment, c_comment});
    // 读取文件数据
    std::vector<int> custkey;
    std::vector<std::string> name;
    std::vector<std::string> address;
    std::vector<int> nationkey;
    std::vector<std::string> phone;
    std::vector<float> acctbal;
    std::vector<std::string> mktsegment;
    std::vector<std::string> comment;
    std::ifstream infile(fileName);
    std::string line;
    if (!infile.is_open()) {
        std::cerr << "无法打开文件" << std::endl;
        return;
    }
    int count = 0;
    int round = 0;
    while (std::getline(infile, line)) {
        std::istringstream iss(line);
        std::string part;
        std::vector<std::string> parts;
        while (std::getline(iss, part, '|')) {
            parts.emplace_back(part);
        }
        custkey.push_back(std::stoi(parts[0]));
        name.push_back(parts[1]);
        address.push_back(parts[2]);
        nationkey.push_back(std::stoi(parts[3]));
        phone.push_back(parts[4]);
        acctbal.push_back(std::stof(parts[5]));
        mktsegment.push_back(parts[6]);
        comment.emplace_back(parts[7]);
        count++;
        if(count == CHUNK_SZIE) {
            round++;
            std::shared_ptr<arrow::Array> custkey_array;
            std::shared_ptr<arrow::Array> name_array;
            std::shared_ptr<arrow::Array> address_array;
            std::shared_ptr<arrow::Array> nationkey_array;
            std::shared_ptr<arrow::Array> phone_array;
            std::shared_ptr<arrow::Array> acctbal_array;
            std::shared_ptr<arrow::Array> mktsegment_array;
            std::shared_ptr<arrow::Array> comment_array;
            ok = DaseX::Util::AppendIntArray(custkey_array, custkey);
            ok = DaseX::Util::AppendStringArray(name_array, name);
            ok = DaseX::Util::AppendStringArray(address_array, address);
            ok = DaseX::Util::AppendIntArray(nationkey_array, nationkey);
            ok = DaseX::Util::AppendStringArray(phone_array, phone);
            ok = DaseX::Util::AppendFloatArray(acctbal_array, acctbal);
            ok = DaseX::Util::AppendStringArray(mktsegment_array, mktsegment);
            ok = DaseX::Util::AppendStringArray(comment_array, comment);
            std::shared_ptr<arrow::RecordBatch> rbatch;
            rbatch = arrow::RecordBatch::Make(schema, CHUNK_SZIE, {custkey_array, name_array, address_array, nationkey_array, phone_array, acctbal_array, mktsegment_array, comment_array});
            table->insert_data(rbatch, partition_idx);
            count = 0;
            // 清空向量
            custkey.clear();
            name.clear();
            address.clear();
            nationkey.clear();
            phone.clear();
            acctbal.clear();
            mktsegment.clear();
            comment.clear();
        }
    }
    if(count != 0) {
        std::shared_ptr<arrow::Array> custkey_array;
        std::shared_ptr<arrow::Array> name_array;
        std::shared_ptr<arrow::Array> address_array;
        std::shared_ptr<arrow::Array> nationkey_array;
        std::shared_ptr<arrow::Array> phone_array;
        std::shared_ptr<arrow::Array> acctbal_array;
        std::shared_ptr<arrow::Array> mktsegment_array;
        std::shared_ptr<arrow::Array> comment_array;
        ok = DaseX::Util::AppendIntArray(custkey_array, custkey);
        ok = DaseX::Util::AppendStringArray(name_array, name);
        ok = DaseX::Util::AppendStringArray(address_array, address);
        ok = DaseX::Util::AppendIntArray(nationkey_array, nationkey);
        ok = DaseX::Util::AppendStringArray(phone_array, phone);
        ok = DaseX::Util::AppendFloatArray(acctbal_array, acctbal);
        ok = DaseX::Util::AppendStringArray(mktsegment_array, mktsegment);
        ok = DaseX::Util::AppendStringArray(comment_array, comment);
        std::shared_ptr<arrow::RecordBatch> rbatch;
        rbatch = arrow::RecordBatch::Make(schema, count, {custkey_array, name_array, address_array, nationkey_array, phone_array, acctbal_array, mktsegment_array, comment_array});
        table->insert_data(rbatch, partition_idx);
    }
    spdlog::info("[{} : {}] The round is: {}, the final count is: {} .", __FILE__, __LINE__, round, count);
    infile.close();
    importFinish = true;
    cv.notify_all();
}

void ImportDataFromOrders(std::shared_ptr<Table> &table, int partition_idx, std::string &fileName) {
    arrow::Status ok;
    // 构建Schema
    std::shared_ptr<arrow::Field> o_orderkey, o_custkey, o_orderstatus, o_totalprice, o_orderdate, o_orderpriority, o_clerk, o_shippriority, o_comment;
    std::shared_ptr<arrow::Schema> schema;
    o_orderkey = arrow::field("o_orderkey", arrow::int32());
    o_custkey = arrow::field("o_custkey", arrow::int32());
    o_orderstatus = arrow::field("o_orderstatus", arrow::utf8());
    o_totalprice = arrow::field("o_totalprice", arrow::float32());
    o_orderdate = arrow::field("o_orderdate", arrow::int32());
    o_orderpriority = arrow::field("o_orderpriority", arrow::utf8());
    o_clerk = arrow::field("o_clerk", arrow::utf8());
    o_shippriority = arrow::field("o_shippriority", arrow::int32());
    o_comment = arrow::field("o_comment", arrow::utf8());
    schema = arrow::schema({o_orderkey, o_custkey, o_orderstatus, o_totalprice, o_orderdate, o_orderpriority, o_clerk, o_shippriority, o_comment});
    // 读取文件数据
    std::vector<int> orderkey;
    std::vector<int> custkey;
    std::vector<std::string> orderstatus;
    std::vector<float> totalprice;
    std::vector<int> orderdate;
    std::vector<std::string> orderpriority;
    std::vector<std::string> clerk;
    std::vector<int> shippriority;
    std::vector<std::string> comment;
    std::ifstream infile(fileName);
    std::string line;
    if (!infile.is_open()) {
        std::cerr << "无法打开文件" << std::endl;
        return;
    }
    int count = 0;
    int round = 0;
    while (std::getline(infile, line)) {
        std::istringstream iss(line);
        std::string part;
        std::vector<std::string> parts;
        while (std::getline(iss, part, '|')) {
            parts.emplace_back(part);
        }
        orderkey.push_back(std::stoi(parts[0]));
        custkey.push_back(std::stoi(parts[1]));
        orderstatus.push_back(parts[2]);
        totalprice.push_back(std::stof(parts[3]));
        orderdate.push_back(std::stoi(parts[4]));
        orderpriority.push_back(parts[5]);
        clerk.push_back(parts[6]);
        shippriority.push_back(std::stoi(parts[7]));
        comment.emplace_back(parts[8]);
        count++;
        if(count == CHUNK_SZIE) {
            round++;
            std::shared_ptr<arrow::Array> orderkey_array;
            std::shared_ptr<arrow::Array> custkey_array;
            std::shared_ptr<arrow::Array> orderstatus_array;
            std::shared_ptr<arrow::Array> totalprice_array;
            std::shared_ptr<arrow::Array> orderdate_array;
            std::shared_ptr<arrow::Array> orderpriority_array;
            std::shared_ptr<arrow::Array> clerk_array;
            std::shared_ptr<arrow::Array> shippriority_array;
            std::shared_ptr<arrow::Array> comment_array;
            ok = DaseX::Util::AppendIntArray(orderkey_array, orderkey);
            ok = DaseX::Util::AppendIntArray(custkey_array, custkey);
            ok = DaseX::Util::AppendStringArray(orderstatus_array, orderstatus);
            ok = DaseX::Util::AppendFloatArray(totalprice_array, totalprice);
            ok = DaseX::Util::AppendIntArray(orderdate_array, orderdate);
            ok = DaseX::Util::AppendStringArray(orderpriority_array, orderpriority);
            ok = DaseX::Util::AppendStringArray(clerk_array, clerk);
            ok = DaseX::Util::AppendIntArray(shippriority_array, shippriority);
            ok = DaseX::Util::AppendStringArray(comment_array, comment);
            std::shared_ptr<arrow::RecordBatch> rbatch;
            rbatch = arrow::RecordBatch::Make(schema, CHUNK_SZIE, {orderkey_array, custkey_array, orderstatus_array, totalprice_array, orderdate_array, orderpriority_array, clerk_array, shippriority_array, comment_array});
            table->insert_data(rbatch, partition_idx);
            count = 0;
            // 清空向量
            orderkey.clear();
            custkey.clear();
            orderstatus.clear();
            totalprice.clear();
            orderdate.clear();
            orderpriority.clear();
            clerk.clear();
            shippriority.clear();
            comment.clear();
        }
    }
    if(count != 0) {
        std::shared_ptr<arrow::Array> orderkey_array;
        std::shared_ptr<arrow::Array> custkey_array;
        std::shared_ptr<arrow::Array> orderstatus_array;
        std::shared_ptr<arrow::Array> totalprice_array;
        std::shared_ptr<arrow::Array> orderdate_array;
        std::shared_ptr<arrow::Array> orderpriority_array;
        std::shared_ptr<arrow::Array> clerk_array;
        std::shared_ptr<arrow::Array> shippriority_array;
        std::shared_ptr<arrow::Array> comment_array;
        ok = DaseX::Util::AppendIntArray(orderkey_array, orderkey);
        ok = DaseX::Util::AppendIntArray(custkey_array, custkey);
        ok = DaseX::Util::AppendStringArray(orderstatus_array, orderstatus);
        ok = DaseX::Util::AppendFloatArray(totalprice_array, totalprice);
        ok = DaseX::Util::AppendIntArray(orderdate_array, orderdate);
        ok = DaseX::Util::AppendStringArray(orderpriority_array, orderpriority);
        ok = DaseX::Util::AppendStringArray(clerk_array, clerk);
        ok = DaseX::Util::AppendIntArray(shippriority_array, shippriority);
        ok = DaseX::Util::AppendStringArray(comment_array, comment);
        std::shared_ptr<arrow::RecordBatch> rbatch;
        rbatch = arrow::RecordBatch::Make(schema, count, {orderkey_array, custkey_array, orderstatus_array, totalprice_array, orderdate_array, orderpriority_array, clerk_array, shippriority_array, comment_array});
        table->insert_data(rbatch, partition_idx);
    }
    spdlog::info("[{} : {}] The round is: {}, the final count is: {} .", __FILE__, __LINE__, round, count);
    infile.close();
    importFinish = true;
    cv.notify_all();
}

void ImportDataFromLineitem(std::shared_ptr<Table> &table, int partition_idx, std::string &fileName) {
    arrow::Status ok;
    // 构建Schema
    std::shared_ptr<arrow::Field> l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment;
    std::shared_ptr<arrow::Schema> schema;
    l_orderkey = arrow::field("l_orderkey", arrow::int32());
    l_partkey = arrow::field("l_partkey", arrow::int32());
    l_suppkey = arrow::field("l_suppkey", arrow::int32());
    l_linenumber = arrow::field("l_linenumber", arrow::int32());
    l_quantity = arrow::field("l_quantity", arrow::float32());
    l_extendedprice = arrow::field("l_extendedprice", arrow::float32());
    l_discount = arrow::field("l_discount", arrow::float32());
    l_tax = arrow::field("l_tax", arrow::float32());
    l_returnflag = arrow::field("l_returnflag", arrow::utf8());
    l_linestatus = arrow::field("l_linestatus", arrow::utf8());
    l_shipdate = arrow::field("l_shipdate", arrow::int32());
    l_commitdate = arrow::field("l_commitdate", arrow::int32());
    l_receiptdate = arrow::field("l_receiptdate", arrow::int32());
    l_shipinstruct = arrow::field("l_shipinstruct", arrow::utf8());
    l_shipmode = arrow::field("l_shipmode", arrow::utf8());
    l_comment = arrow::field("l_comment", arrow::utf8());
    schema = arrow::schema({l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment});
    // 读取文件数据
    std::vector<int> orderkey;
    std::vector<int> partkey;
    std::vector<int> suppkey;
    std::vector<int> linenumber;
    std::vector<float> quantity;
    std::vector<float> extendedprice;
    std::vector<float> discount;
    std::vector<float> tax;
    std::vector<std::string> returnflag;
    std::vector<std::string> linestatus;
    std::vector<int> shipdate;
    std::vector<int> commitdate;
    std::vector<int> receiptdate;
    std::vector<std::string> shipinstruct;
    std::vector<std::string> shipmode;
    std::vector<std::string> comment;
    std::ifstream infile(fileName);
    std::string line;
    if (!infile.is_open()) {
        std::cerr << "无法打开文件" << std::endl;
        return;
    }
    int count = 0;
    int round = 0;
    while (std::getline(infile, line)) {
        std::istringstream iss(line);
        std::string part;
        std::vector<std::string> parts;
        while (std::getline(iss, part, '|')) {
            parts.emplace_back(part);
        }
        orderkey.push_back(std::stoi(parts[0]));
        partkey.push_back(std::stoi(parts[1]));
        suppkey.push_back(std::stoi(parts[2]));
        linenumber.push_back(std::stoi(parts[3]));
        quantity.push_back(std::stof(parts[4]));
        extendedprice.push_back(std::stof(parts[5]));
        discount.push_back(std::stof(parts[6]));
        tax.push_back(std::stof(parts[7]));
        returnflag.emplace_back(parts[8]);
        linestatus.emplace_back(parts[9]);
        shipdate.push_back(std::stoi(parts[10]));
        commitdate.push_back(std::stoi(parts[11]));
        receiptdate.push_back(std::stoi(parts[12]));
        shipinstruct.emplace_back(parts[13]);
        shipmode.emplace_back(parts[14]);
        comment.emplace_back(parts[15]);
        count++;
        if(count == CHUNK_SZIE) {
            round++;
            std::shared_ptr<arrow::Array> orderkey_array;
            std::shared_ptr<arrow::Array> partkey_array;
            std::shared_ptr<arrow::Array> suppkey_array;
            std::shared_ptr<arrow::Array> linenumber_array;
            std::shared_ptr<arrow::Array> quantity_array;
            std::shared_ptr<arrow::Array> extendedprice_array;
            std::shared_ptr<arrow::Array> discount_array;
            std::shared_ptr<arrow::Array> tax_array;
            std::shared_ptr<arrow::Array> returnflag_array;
            std::shared_ptr<arrow::Array> linestatus_array;
            std::shared_ptr<arrow::Array> shipdate_array;
            std::shared_ptr<arrow::Array> commitdate_array;
            std::shared_ptr<arrow::Array> receiptdate_array;
            std::shared_ptr<arrow::Array> shipinstruct_array;
            std::shared_ptr<arrow::Array> shipmode_array;
            std::shared_ptr<arrow::Array> comment_array;
            ok = DaseX::Util::AppendIntArray(orderkey_array, orderkey);
            ok = DaseX::Util::AppendIntArray(partkey_array, partkey);
            ok = DaseX::Util::AppendIntArray(suppkey_array, suppkey);
            ok = DaseX::Util::AppendIntArray(linenumber_array, linenumber);
            ok = DaseX::Util::AppendFloatArray(quantity_array, quantity);
            ok = DaseX::Util::AppendFloatArray(extendedprice_array, extendedprice);
            ok = DaseX::Util::AppendFloatArray(discount_array, discount);
            ok = DaseX::Util::AppendFloatArray(tax_array, tax);
            ok = DaseX::Util::AppendStringArray(returnflag_array, returnflag);
            ok = DaseX::Util::AppendStringArray(linestatus_array, linestatus);
            ok = DaseX::Util::AppendIntArray(shipdate_array, shipdate);
            ok = DaseX::Util::AppendIntArray(commitdate_array, commitdate);
            ok = DaseX::Util::AppendIntArray(receiptdate_array, receiptdate);
            ok = DaseX::Util::AppendStringArray(shipinstruct_array, shipinstruct);
            ok = DaseX::Util::AppendStringArray(shipmode_array, shipmode);
            ok = DaseX::Util::AppendStringArray(comment_array, comment);
            std::shared_ptr<arrow::RecordBatch> rbatch;
            rbatch = arrow::RecordBatch::Make(schema, CHUNK_SZIE, {orderkey_array, partkey_array, suppkey_array, linenumber_array, quantity_array, extendedprice_array, discount_array, tax_array, returnflag_array, linestatus_array, shipdate_array, commitdate_array, receiptdate_array, shipinstruct_array, shipmode_array, comment_array});
            table->insert_data(rbatch, partition_idx);
            count = 0;
            // 清空向量
            orderkey.clear();
            partkey.clear();
            suppkey.clear();
            linenumber.clear();
            quantity.clear();
            extendedprice.clear();
            discount.clear();
            tax.clear();
            returnflag.clear();
            linestatus.clear();
            shipdate.clear();
            commitdate.clear();
            receiptdate.clear();
            shipinstruct.clear();
            shipmode.clear();
            comment.clear();
        }
    }
    if(count != 0) {
        std::shared_ptr<arrow::Array> orderkey_array;
        std::shared_ptr<arrow::Array> partkey_array;
        std::shared_ptr<arrow::Array> suppkey_array;
        std::shared_ptr<arrow::Array> linenumber_array;
        std::shared_ptr<arrow::Array> quantity_array;
        std::shared_ptr<arrow::Array> extendedprice_array;
        std::shared_ptr<arrow::Array> discount_array;
        std::shared_ptr<arrow::Array> tax_array;
        std::shared_ptr<arrow::Array> returnflag_array;
        std::shared_ptr<arrow::Array> linestatus_array;
        std::shared_ptr<arrow::Array> shipdate_array;
        std::shared_ptr<arrow::Array> commitdate_array;
        std::shared_ptr<arrow::Array> receiptdate_array;
        std::shared_ptr<arrow::Array> shipinstruct_array;
        std::shared_ptr<arrow::Array> shipmode_array;
        std::shared_ptr<arrow::Array> comment_array;
        ok = DaseX::Util::AppendIntArray(orderkey_array, orderkey);
        ok = DaseX::Util::AppendIntArray(partkey_array, partkey);
        ok = DaseX::Util::AppendIntArray(suppkey_array, suppkey);
        ok = DaseX::Util::AppendIntArray(linenumber_array, linenumber);
        ok = DaseX::Util::AppendFloatArray(quantity_array, quantity);
        ok = DaseX::Util::AppendFloatArray(extendedprice_array, extendedprice);
        ok = DaseX::Util::AppendFloatArray(discount_array, discount);
        ok = DaseX::Util::AppendFloatArray(tax_array, tax);
        ok = DaseX::Util::AppendStringArray(returnflag_array, returnflag);
        ok = DaseX::Util::AppendStringArray(linestatus_array, linestatus);
        ok = DaseX::Util::AppendIntArray(shipdate_array, shipdate);
        ok = DaseX::Util::AppendIntArray(commitdate_array, commitdate);
        ok = DaseX::Util::AppendIntArray(receiptdate_array, receiptdate);
        ok = DaseX::Util::AppendStringArray(shipinstruct_array, shipinstruct);
        ok = DaseX::Util::AppendStringArray(shipmode_array, shipmode);
        ok = DaseX::Util::AppendStringArray(comment_array, comment);
        std::shared_ptr<arrow::RecordBatch> rbatch;
        rbatch = arrow::RecordBatch::Make(schema, count, {orderkey_array, partkey_array, suppkey_array, linenumber_array, quantity_array, extendedprice_array, discount_array, tax_array, returnflag_array, linestatus_array, shipdate_array, commitdate_array, receiptdate_array, shipinstruct_array, shipmode_array, comment_array});
        table->insert_data(rbatch, partition_idx);
    }
    spdlog::info("[{} : {}] The round is: {}, the final count is: {} .", __FILE__, __LINE__, round, count);
    infile.close();
    importFinish = true;
    cv.notify_all();
}

void ImportDataFromRevenue(std::shared_ptr<Table> &table, int partition_idx, std::string &fileName) {
    arrow::Status ok;
    // 构建Schema
    std::shared_ptr<arrow::Field> supplier_no, total_revenue;
    std::shared_ptr<arrow::Schema> schema;
    supplier_no = arrow::field("supplier_no", arrow::int32());
    total_revenue = arrow::field("total_revenue", arrow::float64());
    schema = arrow::schema({supplier_no, total_revenue});
    // 读取文件数据
    std::vector<int> supplier;
    std::vector<double> revenue;
    std::ifstream infile(fileName);
    std::string line;
    if (!infile.is_open()) {
        std::cerr << "无法打开文件" << std::endl;
        return;
    }
    int count = 0;
    int round = 0;
    while (std::getline(infile, line)) {
        std::istringstream iss(line);
        std::string part;
        std::vector<std::string> parts;
        while (std::getline(iss, part, '|')) {
            parts.emplace_back(part);
        }
        supplier.push_back(std::stoi(parts[0]));
        revenue.push_back(std::stod(parts[1]));
        count++;
        if(count == CHUNK_SZIE) {
            round++;
            std::shared_ptr<arrow::Array> supplier_array;
            std::shared_ptr<arrow::Array> revenue_array;
            ok = DaseX::Util::AppendIntArray(supplier_array, supplier);
            ok = DaseX::Util::AppendDoubleArray(revenue_array, revenue);
            std::shared_ptr<arrow::RecordBatch> rbatch;
            rbatch = arrow::RecordBatch::Make(schema, CHUNK_SZIE, {supplier_array, revenue_array});
            table->insert_data(rbatch, partition_idx);
            count = 0;
            // 清空向量
            supplier.clear();
            revenue.clear();
        }
    }
    if(count != 0) {
        std::shared_ptr<arrow::Array> supplier_array;
        std::shared_ptr<arrow::Array> revenue_array;
        ok = DaseX::Util::AppendIntArray(supplier_array, supplier);
        ok = DaseX::Util::AppendDoubleArray(revenue_array, revenue);
        std::shared_ptr<arrow::RecordBatch> rbatch;
        rbatch = arrow::RecordBatch::Make(schema, CHUNK_SZIE, {supplier_array, revenue_array});
        table->insert_data(rbatch, partition_idx);
    }
    spdlog::info("[{} : {}] The round is: {}, the final count is: {} .", __FILE__, __LINE__, round, count);
    infile.close();
    importFinish = true;
    cv.notify_all();
}

void InsertNation(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler) {
    std::vector<std::string> filed_names = {"n_nationkey", "n_name", "n_regionkey", "n_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::STRING;
    LogicalType filed3  = LogicalType::INTEGER;
    LogicalType filed4  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    std::string table_name = "nation";
    TableInfo nation_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(nation_info);
    rc = global_catalog.get_table(table_name, table);
    std::string fileName = fileDir + "/" + "nation.tbl";
    scheduler->submit_task(ImportDataFromNation, 1, true, std::ref(table), 1, std::ref(fileName));
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertRegion(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler) {
    std::vector<std::string> filed_names = {"r_regionkey", "r_name", "r_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::STRING;
    LogicalType filed3  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    std::string table_name = "region";
    TableInfo region_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(region_info);
    rc = global_catalog.get_table(table_name, table);
    std::string fileName = fileDir + "/" + "region.tbl";
    scheduler->submit_task(ImportDataFromRegion, 1, true, std::ref(table), 1, std::ref(fileName));
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertPart(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler) {
    std::vector<std::string> filed_names = {"p_partkey", "p_name", "p_mfgr", "p_brand", "p_type", "p_size", "p_container", "p_retailprice", "p_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::STRING;
    LogicalType filed3  = LogicalType::STRING;
    LogicalType filed4  = LogicalType::STRING;
    LogicalType filed5  = LogicalType::STRING;
    LogicalType filed6  = LogicalType::INTEGER;
    LogicalType filed7  = LogicalType::STRING;
    LogicalType filed8  = LogicalType::FLOAT;
    LogicalType filed9  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    filed_types.push_back(filed6);
    filed_types.push_back(filed7);
    filed_types.push_back(filed8);
    filed_types.push_back(filed9);
    std::string table_name = "part";
    TableInfo part_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(part_info);
    rc = global_catalog.get_table(table_name, table);
    std::string fileName = fileDir + "/" + "part.tbl";
    scheduler->submit_task(ImportDataFromPart, 1, true, std::ref(table), 1, std::ref(fileName));
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertSupplier(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler) {
    std::vector<std::string> filed_names = {"s_suppkey", "s_name", "s_address", "s_nationkey", "s_phone", "s_acctbal", "s_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::STRING;
    LogicalType filed3  = LogicalType::STRING;
    LogicalType filed4  = LogicalType::INTEGER;
    LogicalType filed5  = LogicalType::STRING;
    LogicalType filed6  = LogicalType::FLOAT;
    LogicalType filed7  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    filed_types.push_back(filed6);
    filed_types.push_back(filed7);
    std::string table_name = "supplier";
    TableInfo supplier_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(supplier_info);
    rc = global_catalog.get_table(table_name, table);
    std::string fileName = fileDir + "/" + "supplier.tbl";
    scheduler->submit_task(ImportDataFromSupplier, 1, true, std::ref(table), 1, std::ref(fileName));
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertPartsupp(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler) {
    std::vector<std::string> filed_names = {"ps_partkey", "ps_suppkey", "ps_availqty", "ps_supplycost", "ps_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::INTEGER;
    LogicalType filed3  = LogicalType::INTEGER;
    LogicalType filed4  = LogicalType::FLOAT;
    LogicalType filed5  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    std::string table_name = "partsupp";
    TableInfo partsupp_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(partsupp_info);
    rc = global_catalog.get_table(table_name, table);
    std::string fileName = fileDir + "/" + "partsupp.tbl";
    scheduler->submit_task(ImportDataFromPartsupp, 1, true, std::ref(table), 1, std::ref(fileName));
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertCustomer(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler) {
    std::vector<std::string> filed_names = {"c_custkey", "c_name", "c_address", "c_nationkey", "c_phone", "c_acctbal", "c_mktsegment", "c_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::STRING;
    LogicalType filed3  = LogicalType::STRING;
    LogicalType filed4  = LogicalType::INTEGER;
    LogicalType filed5  = LogicalType::STRING;
    LogicalType filed6  = LogicalType::FLOAT;
    LogicalType filed7  = LogicalType::STRING;
    LogicalType filed8  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    filed_types.push_back(filed6);
    filed_types.push_back(filed7);
    filed_types.push_back(filed8);
    std::string table_name = "customer";
    TableInfo customer_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(customer_info);
    rc = global_catalog.get_table(table_name, table);
    std::string fileName = fileDir + "/" + "customer.tbl";
    scheduler->submit_task(ImportDataFromCustomer, 1, true, std::ref(table), 1, std::ref(fileName));
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertOrders(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler) {
    std::vector<std::string> filed_names = {"o_orderkey", "o_custkey", "o_orderstatus", "o_totalprice", "o_orderdate", "o_orderpriority", "o_clerk", "o_shippriority", "o_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::INTEGER;
    LogicalType filed3  = LogicalType::STRING;
    LogicalType filed4  = LogicalType::FLOAT;
    LogicalType filed5  = LogicalType::INTEGER;
    LogicalType filed6  = LogicalType::STRING;
    LogicalType filed7  = LogicalType::STRING;
    LogicalType filed8  = LogicalType::INTEGER;
    LogicalType filed9  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    filed_types.push_back(filed6);
    filed_types.push_back(filed7);
    filed_types.push_back(filed8);
    filed_types.push_back(filed9);
    std::string table_name = "orders";
    TableInfo orders_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(orders_info);
    rc = global_catalog.get_table(table_name, table);
    std::string fileName = fileDir + "/" + "orders.tbl";
    scheduler->submit_task(ImportDataFromOrders, 1, true, std::ref(table), 1, std::ref(fileName));
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertLineitem(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler) {
    std::vector<std::string> filed_names = {"l_orderkey", "l_partkey", "l_suppkey", "l_linenumber", "l_quantity", "l_extendedprice", "l_discount", "l_tax", "l_returnflag", "l_linestatus", "l_shipdate", "l_commitdate", "l_receiptdate", "l_shipinstruct", "l_shipmode", "l_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::INTEGER;
    LogicalType filed3  = LogicalType::INTEGER;
    LogicalType filed4  = LogicalType::INTEGER;
    LogicalType filed5  = LogicalType::FLOAT;
    LogicalType filed6  = LogicalType::FLOAT;
    LogicalType filed7  = LogicalType::FLOAT;
    LogicalType filed8  = LogicalType::FLOAT;
    LogicalType filed9  = LogicalType::STRING;
    LogicalType filed10 = LogicalType::STRING;
    LogicalType filed11 = LogicalType::INTEGER;
    LogicalType filed12 = LogicalType::INTEGER;
    LogicalType filed13 = LogicalType::INTEGER;
    LogicalType filed14 = LogicalType::STRING;
    LogicalType filed15 = LogicalType::STRING;
    LogicalType filed16 = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    filed_types.push_back(filed6);
    filed_types.push_back(filed7);
    filed_types.push_back(filed8);
    filed_types.push_back(filed9);
    filed_types.push_back(filed10);
    filed_types.push_back(filed11);
    filed_types.push_back(filed12);
    filed_types.push_back(filed13);
    filed_types.push_back(filed14);
    filed_types.push_back(filed15);
    filed_types.push_back(filed16);
    std::string table_name = "lineitem";
    TableInfo lineitem_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(lineitem_info);
    rc = global_catalog.get_table(table_name, table);
    std::string fileName = fileDir + "/" + "lineitem.tbl";
    scheduler->submit_task(ImportDataFromLineitem, 1, true, std::ref(table), 1, std::ref(fileName));
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertRevenue(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler) {
    std::vector<std::string> filed_names = {"supplier_no", "total_revenue"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::DOUBLE;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    std::string table_name = "revenue";
    TableInfo revenue_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(revenue_info);
    rc = global_catalog.get_table(table_name, table);
    std::string fileName = fileDir + "/" + "revenue.tbl";
    scheduler->submit_task(ImportDataFromRevenue, 1, true, std::ref(table), 1, std::ref(fileName));
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertNationMul(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler, std::vector<int> &work_ids, std::vector<int> &partition_idxs, std::vector<std::string> &file_names) {
    std::vector<std::string> filed_names = {"n_nationkey", "n_name", "n_regionkey", "n_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::STRING;
    LogicalType filed3  = LogicalType::INTEGER;
    LogicalType filed4  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    std::string table_name = "nation";
    TableInfo nation_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(nation_info);
    rc = global_catalog.get_table(table_name, table);
    int size = work_ids.size();
    for(int i = 0; i < size; i++) {
        scheduler->submit_task(ImportDataFromNation, work_ids[i], true, std::ref(table), partition_idxs[i], std::ref(file_names[i]));
    }
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertRegionMul(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler, std::vector<int> &work_ids, std::vector<int> &partition_idxs, std::vector<std::string> &file_names) {
    std::vector<std::string> filed_names = {"r_regionkey", "r_name", "r_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::STRING;
    LogicalType filed3  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    std::string table_name = "region";
    TableInfo region_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(region_info);
    rc = global_catalog.get_table(table_name, table);
    int size = work_ids.size();
    for(int i = 0; i < size; i++) {
        scheduler->submit_task(ImportDataFromRegion, work_ids[i], true, std::ref(table), partition_idxs[i], std::ref(file_names[i]));
    }
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertPartMul(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler, std::vector<int> &work_ids, std::vector<int> &partition_idxs, std::vector<std::string> &file_names) {
    std::vector<std::string> filed_names = {"p_partkey", "p_name", "p_mfgr", "p_brand", "p_type", "p_size", "p_container", "p_retailprice", "p_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::STRING;
    LogicalType filed3  = LogicalType::STRING;
    LogicalType filed4  = LogicalType::STRING;
    LogicalType filed5  = LogicalType::STRING;
    LogicalType filed6  = LogicalType::INTEGER;
    LogicalType filed7  = LogicalType::STRING;
    LogicalType filed8  = LogicalType::FLOAT;
    LogicalType filed9  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    filed_types.push_back(filed6);
    filed_types.push_back(filed7);
    filed_types.push_back(filed8);
    filed_types.push_back(filed9);
    std::string table_name = "part";
    TableInfo part_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(part_info);
    rc = global_catalog.get_table(table_name, table);
    int size = work_ids.size();
    for(int i = 0; i < size; i++) {
        scheduler->submit_task(ImportDataFromPart, work_ids[i], true, std::ref(table), partition_idxs[i], std::ref(file_names[i]));
    }
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertSupplierMul(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler, std::vector<int> &work_ids, std::vector<int> &partition_idxs, std::vector<std::string> &file_names) {
    std::vector<std::string> filed_names = {"s_suppkey", "s_name", "s_address", "s_nationkey", "s_phone", "s_acctbal", "s_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::STRING;
    LogicalType filed3  = LogicalType::STRING;
    LogicalType filed4  = LogicalType::INTEGER;
    LogicalType filed5  = LogicalType::STRING;
    LogicalType filed6  = LogicalType::FLOAT;
    LogicalType filed7  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    filed_types.push_back(filed6);
    filed_types.push_back(filed7);
    std::string table_name = "supplier";
    TableInfo supplier_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(supplier_info);
    rc = global_catalog.get_table(table_name, table);
    int size = work_ids.size();
    for(int i = 0; i < size; i++) {
        scheduler->submit_task(ImportDataFromSupplier, work_ids[i], true, std::ref(table), partition_idxs[i], std::ref(file_names[i]));
    }
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertPartsuppMul(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler, std::vector<int> &work_ids, std::vector<int> &partition_idxs, std::vector<std::string> &file_names) {
    std::vector<std::string> filed_names = {"ps_partkey", "ps_suppkey", "ps_availqty", "ps_supplycost", "ps_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::INTEGER;
    LogicalType filed3  = LogicalType::INTEGER;
    LogicalType filed4  = LogicalType::FLOAT;
    LogicalType filed5  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    std::string table_name = "partsupp";
    TableInfo partsupp_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(partsupp_info);
    rc = global_catalog.get_table(table_name, table);
    int size = work_ids.size();
    for(int i = 0; i < size; i++) {
        scheduler->submit_task(ImportDataFromPartsupp, work_ids[i], true, std::ref(table), partition_idxs[i], std::ref(file_names[i]));
    }
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertCustomerMul(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler, std::vector<int> &work_ids, std::vector<int> &partition_idxs, std::vector<std::string> &file_names) {
    std::vector<std::string> filed_names = {"c_custkey", "c_name", "c_address", "c_nationkey", "c_phone", "c_acctbal", "c_mktsegment", "c_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::STRING;
    LogicalType filed3  = LogicalType::STRING;
    LogicalType filed4  = LogicalType::INTEGER;
    LogicalType filed5  = LogicalType::STRING;
    LogicalType filed6  = LogicalType::FLOAT;
    LogicalType filed7  = LogicalType::STRING;
    LogicalType filed8  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    filed_types.push_back(filed6);
    filed_types.push_back(filed7);
    filed_types.push_back(filed8);
    std::string table_name = "customer";
    TableInfo customer_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(customer_info);
    rc = global_catalog.get_table(table_name, table);
    int size = work_ids.size();
    for(int i = 0; i < size; i++) {
        scheduler->submit_task(ImportDataFromCustomer, work_ids[i], true, std::ref(table), partition_idxs[i], std::ref(file_names[i]));
    }
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertOrdersMul(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler, std::vector<int> &work_ids, std::vector<int> &partition_idxs, std::vector<std::string> &file_names) {
    std::vector<std::string> filed_names = {"o_orderkey", "o_custkey", "o_orderstatus", "o_totalprice", "o_orderdate", "o_orderpriority", "o_clerk", "o_shippriority", "o_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::INTEGER;
    LogicalType filed3  = LogicalType::STRING;
    LogicalType filed4  = LogicalType::FLOAT;
    LogicalType filed5  = LogicalType::INTEGER;
    LogicalType filed6  = LogicalType::STRING;
    LogicalType filed7  = LogicalType::STRING;
    LogicalType filed8  = LogicalType::INTEGER;
    LogicalType filed9  = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    filed_types.push_back(filed6);
    filed_types.push_back(filed7);
    filed_types.push_back(filed8);
    filed_types.push_back(filed9);
    std::string table_name = "orders";
    TableInfo orders_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(orders_info);
    rc = global_catalog.get_table(table_name, table);
    int size = work_ids.size();
    for(int i = 0; i < size; i++) {
        scheduler->submit_task(ImportDataFromOrders, work_ids[i], true, std::ref(table), partition_idxs[i], std::ref(file_names[i]));
    }
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

// 多线程插入LineItem表，需要额外指定线程id, 要插入的表分区以及文件名。例如，如果要用4个线程插入lineitem.tbl数据，需要将其预处理分为4个文件，命名方式为lineitem.tbl_0、lineitem.tbl_1、lineitem.tbl_2、lineitem.tbl_3
void InsertLineitemMul(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler, std::vector<int> &work_ids, std::vector<int> &partition_idxs, std::vector<std::string> &file_names) {
    std::vector<std::string> filed_names = {"l_orderkey", "l_partkey", "l_suppkey", "l_linenumber", "l_quantity", "l_extendedprice", "l_discount", "l_tax", "l_returnflag", "l_linestatus", "l_shipdate", "l_commitdate", "l_receiptdate", "l_shipinstruct", "l_shipmode", "l_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::INTEGER;
    LogicalType filed3  = LogicalType::INTEGER;
    LogicalType filed4  = LogicalType::INTEGER;
    LogicalType filed5  = LogicalType::FLOAT;
    LogicalType filed6  = LogicalType::FLOAT;
    LogicalType filed7  = LogicalType::FLOAT;
    LogicalType filed8  = LogicalType::FLOAT;
    LogicalType filed9  = LogicalType::STRING;
    LogicalType filed10 = LogicalType::STRING;
    LogicalType filed11 = LogicalType::INTEGER;
    LogicalType filed12 = LogicalType::INTEGER;
    LogicalType filed13 = LogicalType::INTEGER;
    LogicalType filed14 = LogicalType::STRING;
    LogicalType filed15 = LogicalType::STRING;
    LogicalType filed16 = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    filed_types.push_back(filed6);
    filed_types.push_back(filed7);
    filed_types.push_back(filed8);
    filed_types.push_back(filed9);
    filed_types.push_back(filed10);
    filed_types.push_back(filed11);
    filed_types.push_back(filed12);
    filed_types.push_back(filed13);
    filed_types.push_back(filed14);
    filed_types.push_back(filed15);
    filed_types.push_back(filed16);
    std::string table_name = "lineitem";
    TableInfo lineitem_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(lineitem_info);
    rc = global_catalog.get_table(table_name, table);
    int size = work_ids.size();
    for(int i = 0; i < size; i++) {
        scheduler->submit_task(ImportDataFromLineitem, work_ids[i], true, std::ref(table), partition_idxs[i], std::ref(file_names[i]));
    }
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

void InsertRevenueMul(std::shared_ptr<Table> &table, std::shared_ptr<Scheduler> &scheduler, std::vector<int> &work_ids, std::vector<int> &partition_idxs, std::vector<std::string> &file_names) {
    std::vector<std::string> filed_names = {"supplier_no", "total_revenue"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::DOUBLE;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    std::string table_name = "revenue";
    TableInfo revenue_info(table_name, filed_names, filed_types);
    RC rc = global_catalog.register_table(revenue_info);
    rc = global_catalog.get_table(table_name, table);
    int size = work_ids.size();
    for(int i = 0; i < size; i++) {
        scheduler->submit_task(ImportDataFromRevenue, work_ids[i], true, std::ref(table), partition_idxs[i], std::ref(file_names[i]));
    }
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
}

// ================================================================TPC-H测试================================================================
// =============================Q1=============================
// 测试Q1,4线程
TEST(TPCHTest, Q1FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    Util::print_socket_free_memory();
    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    // std::vector<int> &work_ids, std::vector<int> &partition_idxs, std::vector<std::string> &file_names
    std::vector<int> work_ids = {1, 2, 3, 4};
    std::vector<int> partition_idxs = {1, 2, 3, 4};
    std::vector<std::string> file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir5 + "/" + "lineitem.tbl_" + std::to_string(i);
        file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, file_names);
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    // 构建Scan
    std::vector<int> projection_ids = {4, 5 ,6 ,7, 8, 9, 10};
    std::shared_ptr<PhysicalTableScan> scan = std::make_shared<PhysicalTableScan>(table_lineitem, -1, projection_ids);

    // 构建Filter
    std::shared_ptr<BoundColumnRefExpression> l_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    Value value_p(875635200);
    std::shared_ptr<BoundConstantExpression> constant_col = std::make_shared<BoundConstantExpression>(value_p);
    std::shared_ptr<BoundComparisonExpression> comparison_col = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, l_shipdate, constant_col);
    std::shared_ptr<PhysicalFilter> filter = std::make_shared<PhysicalFilter>(comparison_col);

    // 构建Project
    std::shared_ptr<BoundColumnRefExpression> l_returnflag = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 4, 0);
    std::shared_ptr<BoundColumnRefExpression> l_linestatus = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> l_tax = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 3, 0);
    Value value_1(1.0f);
    std::shared_ptr<BoundConstantExpression> constant1_col = std::make_shared<BoundConstantExpression>(value_1);
    std::vector<LogicalType> arguments1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function1 = GetSubFunction();
    ScalarProjectFunction bound_function1("-", arguments1, LogicalType::FLOAT, function1, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions1 = {constant1_col, l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function1, expressions1, nullptr);
    discount_1_col->alias = "1-l_discount";
    std::vector<LogicalType> arguments2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function2 = GetMulFunction();
    ScalarProjectFunction bound_function2("*", arguments2, LogicalType::FLOAT, function2, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions2 = {l_extendedprice, discount_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function2, expressions2, nullptr);
    extendedprice_discount_1_col->alias = "l_extendedprice*(1-l_discount)";

    std::vector<LogicalType> arguments3 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function3 = GetAddFunction();
    ScalarProjectFunction bound_function3("+", arguments3, LogicalType::FLOAT, function3, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions3 = {constant1_col, l_tax};
    std::shared_ptr<BoundProjectFunctionExpression> tax_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function3, expressions3, nullptr);
    tax_1_col->alias = "1+l_tax";

    std::vector<LogicalType> arguments4 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function4 = GetMulFunction();
    ScalarProjectFunction bound_function4("*", arguments4, LogicalType::FLOAT, function4, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions4 = {extendedprice_discount_1_col, tax_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_tax_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function4, expressions4, nullptr);
    extendedprice_tax_col->alias = "l_extendedprice*(1-l_discount)*(1+l_tax)";

    std::vector<std::shared_ptr<Expression>> expressions5 = {l_returnflag, l_linestatus, l_quantity, l_extendedprice, extendedprice_discount_1_col, extendedprice_tax_col, l_discount};
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(expressions5);

    // 构建HashAgg
    std::vector<int> group_set = {0, 1};
    std::vector<int> agg_set = {2, 3, 4, 5, 2, 3, 6, 2};
    std::vector<int> star_bitmap = {0, 0, 0, 0, 0, 0, 0, 1};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM, AggFunctionType::SUM, AggFunctionType::SUM, AggFunctionType::SUM, AggFunctionType::AVG, AggFunctionType::AVG, AggFunctionType::AVG, AggFunctionType::COUNT};
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    hashAgg->AddChild(project);
    project->AddChild(filter);
    filter->AddChild(scan);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    hashAgg->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q1执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q2=============================
// 测试Q2Pipeline构建
TEST(TPCHTest, Q2PipelineBuildTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
//    InsertNation(table_nation, scheduler);
//    importFinish = false;
//    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Region表数据
    std::shared_ptr<Table> table_region;
//    InsertRegion(table_region, scheduler);
//    importFinish = false;
//    spdlog::info("[{} : {}] InsertRegion Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_partsupp;
//    InsertOrders(table_orders, scheduler);
//    importFinish = false;
//    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_part;
//    InsertLineitem(table_lineitem, scheduler);
//    importFinish = false;
//    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
//    InsertSupplier(table_supplier, scheduler);
//    importFinish = false;
//    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> region_ids = {0, 1};
    // <r_regionkey, r_name>
    std::shared_ptr<PhysicalTableScan> scan_region = std::make_shared<PhysicalTableScan>(table_region, -1, region_ids);

    std::vector<int> nation_ids = {0, 2};
    // <n_nationkey, n_regionkey>
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> supplier_ids = {0, 3};
    // <s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    std::vector<int> partsupp_ids = {0, 1, 3};
    // <ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalTableScan> scan_partsupp = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);
    //  ================================================构建Filter-region================================================
    std::shared_ptr<BoundColumnRefExpression> left_r_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_ASIA("ASIA");
    std::shared_ptr<BoundConstantExpression> right_r_name = std::make_shared<BoundConstantExpression>(value_ASIA);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_r_name = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_r_name->SetLeft(left_r_name);
    comparisonExpression_r_name->SetRight(right_r_name);
    std::shared_ptr<PhysicalFilter> filter_region = std::make_shared<PhysicalFilter>(comparisonExpression_r_name);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {1};
    std::vector<int> prode_ids1 = {0};
    // <r_regionkey, r_name, l.n_nationkey, l.n_regionkey>
    std::shared_ptr<PhysicalHashJoin> nation_join_region = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);

    std::vector<int> build_ids2 = {1};
    std::vector<int> prode_ids2 = {2};
    // <r_regionkey, r_name, l.n_nationkey, l.n_regionkey, s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalHashJoin> suppliers_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);

    std::vector<int> build_ids3 = {1};
    std::vector<int> prode_ids3 = {4};
    // <r_regionkey, r_name, l.n_nationkey, l.n_regionkey, s_suppkey, s_nationkey, ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalHashJoin> partsupp_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);

    //  ================================================构建Project-1================================================
    std::shared_ptr<BoundColumnRefExpression> p1_ps_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 8, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_ps_partkey, p1_ps_supplycost};
    // <ps_partkey, ps_supplycost>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);

    //  ================================================构建HashAgg================================================
    std::vector<int> group_item_idxs = {1};
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::MIN };
    std::shared_ptr<PhysicalHashAgg> hashAgg = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, group_item_idxs);

    //  ================================================构建Scan================================================
    // <r_regionkey, r_name>
    std::shared_ptr<PhysicalTableScan> scan_region2 = std::make_shared<PhysicalTableScan>(table_region, -1, region_ids);

    std::vector<int> nation_ids2 = {0, 1, 2};
    // <n_nationkey, n_name, n_regionkey>
    std::shared_ptr<PhysicalTableScan> scan_nation2 = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids2);

    // <s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment>
    std::shared_ptr<PhysicalTableScan> scan_supplier2 = std::make_shared<PhysicalTableScan>(table_supplier);

    //  ================================================构建Filter-region2================================================
    std::shared_ptr<BoundColumnRefExpression> left_r_name2 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundConstantExpression> right_r_name2 = std::make_shared<BoundConstantExpression>(value_ASIA);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_r_name2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_r_name2->SetLeft(left_r_name2);
    comparisonExpression_r_name2->SetRight(right_r_name2);
    std::shared_ptr<PhysicalFilter> filter_region2 = std::make_shared<PhysicalFilter>(comparisonExpression_r_name2);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids4 = {1};
    std::vector<int> prode_ids4 = {0};
    // <r_regionkey, r_name, n_nationkey, n_name, n_regionkey>
    std::shared_ptr<PhysicalHashJoin> nation_join_region2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);

    std::vector<int> build_ids5 = {3};
    std::vector<int> prode_ids5 = {2};
    // <r_regionkey, r_name, n_nationkey, n_name, n_regionkey, s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment>
    std::shared_ptr<PhysicalHashJoin> suppliers_join_last2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids5, prode_ids5);

    //  ================================================构建Scan================================================
    std::vector<int> part_ids2 = {0, 2, 4, 5};
    // <p_partkey, p_mfgr, p_type, p_size>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids2);

    //  ================================================构建Filter-part================================================
    std::shared_ptr<BoundColumnRefExpression> left_p_size = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_15(15);
    std::shared_ptr<BoundConstantExpression> right_p_constant = std::make_shared<BoundConstantExpression>(value_15);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_p_size = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_p_size->SetLeft(left_p_size);
    comparisonExpression_p_size->SetRight(right_p_constant);
    // <p_partkey, p_mfgr, p_type, p_size>
    std::shared_ptr<PhysicalFilter> filter_part = std::make_shared<PhysicalFilter>(comparisonExpression_p_size);

    std::string like_pattern = "%BRASS";
    ScalarFunction bound_function = LikeFun::GetLikeFunction();
    std::shared_ptr<BoundColumnRefExpression> left_p_type = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);
    Value value_BRASS(like_pattern);
    std::shared_ptr<BoundConstantExpression> right_p_constant2 = std::make_shared<BoundConstantExpression>(value_BRASS);
    std::vector<std::shared_ptr<Expression>> arguments_part;
    arguments_part.push_back(std::move(left_p_type));
    arguments_part.push_back(std::move(right_p_constant2));
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments_part, nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);
    // <p_partkey, p_mfgr, p_type, p_size>
    std::shared_ptr<PhysicalFilter> filter_part_type = std::make_shared<PhysicalFilter>(functionExpression);

    //  ================================================构建Project-2================================================
    std::shared_ptr<BoundColumnRefExpression> p2_p_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_p_mfgr = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_p_partkey, p2_p_mfgr};
    // <p_partkey, p_mfgr>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);

    //  ================================================构建Scan================================================
    // <ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalTableScan> scan_partsupp2 = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids6 = {0};
    std::vector<int> prode_ids6 = {0};
    // <p_partkey, p_mfgr, ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalHashJoin> partsupp_join_last2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids6, prode_ids6);

    std::vector<int> build_ids7 = {3};
    std::vector<int> prode_ids7 = {5};
    // <r_regionkey, r_name, n_nationkey, n_name, n_regionkey, s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment, p_partkey, p_mfgr, ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalHashJoin> partsupp_join_suppliers = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids7, prode_ids7);

    std::vector<int> build_ids8 = {0};
    std::vector<int> prode_ids8 = {12};
    // <r_regionkey, r_name, n_nationkey, n_name, n_regionkey, s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment, p_partkey, p_mfgr, ps_partkey, ps_suppkey, ps_supplycost, ps_partkey, min(ps_supplycost)>
    std::shared_ptr<PhysicalHashJoin> partsupp_join_suppliers_last = std::make_shared<PhysicalHashJoin>(JoinTypes::LEFT, build_ids8, prode_ids8);

    //  ================================================构建Filter-join================================================
    std::shared_ptr<BoundColumnRefExpression> left_min_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 18, 0);
    std::shared_ptr<BoundColumnRefExpression> right_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 16, 0);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_ps_supplycost = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_ps_supplycost->SetLeft(left_min_ps_supplycost);
    comparisonExpression_ps_supplycost->SetRight(right_ps_supplycost);
    std::shared_ptr<PhysicalFilter> filter_join = std::make_shared<PhysicalFilter>(comparisonExpression_ps_supplycost);

    //  ================================================构建Project-3================================================
    std::shared_ptr<BoundColumnRefExpression> p3_s_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 10, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_s_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_p_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 12, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_p_mfgr = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 13, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_s_address = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 7, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_s_phone = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 9, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_s_comment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 11, 0);
    std::vector<std::shared_ptr<Expression>> p3_expressions = {p3_s_acctbal, p3_s_name, p3_n_name, p3_p_partkey, p3_p_mfgr, p3_s_address, p3_s_phone, p3_s_comment};
    // <s_acctbal, s_name, n_name, p_partkey, p_mfgr, s_address, s_phone, s_comment>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0, 2, 1, 3};
    std::vector<LogicalType> key_types = {LogicalType::FLOAT, LogicalType::STRING, LogicalType::STRING, LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING, SortOrder::ASCENDING, SortOrder::ASCENDING, SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(project3);
    project3->AddChild(filter_join);
    filter_join->AddChild(partsupp_join_suppliers_last);
    partsupp_join_suppliers_last->AddChild(hashAgg);
    partsupp_join_suppliers_last->AddChild(partsupp_join_suppliers);
    hashAgg->AddChild(project1);
    project1->AddChild(partsupp_join_last);
    partsupp_join_last->AddChild(scan_partsupp);
    partsupp_join_last->AddChild(suppliers_join_last);
    suppliers_join_last->AddChild(scan_supplier);
    suppliers_join_last->AddChild(nation_join_region);
    nation_join_region->AddChild(scan_nation);
    nation_join_region->AddChild(filter_region);
    filter_region->AddChild(scan_region);
    partsupp_join_suppliers->AddChild(partsupp_join_last2);
    partsupp_join_suppliers->AddChild(suppliers_join_last2);
    partsupp_join_last2->AddChild(scan_partsupp2);
    partsupp_join_last2->AddChild(project2);
    project2->AddChild(filter_part_type);
    filter_part_type->AddChild(filter_part);
    filter_part->AddChild(scan_part);
    suppliers_join_last2->AddChild(scan_supplier2);
    suppliers_join_last2->AddChild(nation_join_region2);
    nation_join_region2->AddChild(scan_nation2);
    nation_join_region2->AddChild(filter_region2);
    filter_region2->AddChild(scan_region2);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
//    auto start_execute = std::chrono::steady_clock::now();
//    pipeline_group_executor->execute();
//    auto end_execute = std::chrono::steady_clock::now();
//    spdlog::info("[{} : {}] Q2执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试单线程Q2查询
TEST(TPCHTest, Q2SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    InsertNation(table_nation, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Region表数据
    std::shared_ptr<Table> table_region;
    InsertRegion(table_region, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertRegion Finish!!!", __FILE__, __LINE__);

    // 插入Partsupp表数据
    std::shared_ptr<Table> table_partsupp;
    InsertPartsupp(table_partsupp, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPartsupp Finish!!!", __FILE__, __LINE__);

    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    InsertPart(table_part, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    InsertSupplier(table_supplier, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> region_ids = {0, 1};
    // <r_regionkey, r_name>
    std::shared_ptr<PhysicalTableScan> scan_region = std::make_shared<PhysicalTableScan>(table_region, -1, region_ids);

    std::vector<int> nation_ids = {0, 2};
    // <n_nationkey, n_regionkey>
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> supplier_ids = {0, 3};
    // <s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    std::vector<int> partsupp_ids = {0, 1, 3};
    // <ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalTableScan> scan_partsupp = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);
    //  ================================================构建Filter-region================================================
    std::shared_ptr<BoundColumnRefExpression> left_r_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_ASIA("ASIA");
    std::shared_ptr<BoundConstantExpression> right_r_name = std::make_shared<BoundConstantExpression>(value_ASIA);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_r_name = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_r_name->SetLeft(left_r_name);
    comparisonExpression_r_name->SetRight(right_r_name);
    std::shared_ptr<PhysicalFilter> filter_region = std::make_shared<PhysicalFilter>(comparisonExpression_r_name);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {1};
    std::vector<int> prode_ids1 = {0};
    // <r_regionkey, r_name, l.n_nationkey, l.n_regionkey>
    std::shared_ptr<PhysicalHashJoin> nation_join_region = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);

    std::vector<int> build_ids2 = {1};
    std::vector<int> prode_ids2 = {2};
    // <r_regionkey, r_name, l.n_nationkey, l.n_regionkey, s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalHashJoin> suppliers_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);

    std::vector<int> build_ids3 = {1};
    std::vector<int> prode_ids3 = {4};
    // <r_regionkey, r_name, l.n_nationkey, l.n_regionkey, s_suppkey, s_nationkey, ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalHashJoin> partsupp_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    //  ================================================构建Project-1================================================
    std::shared_ptr<BoundColumnRefExpression> p1_ps_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 8, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_ps_partkey, p1_ps_supplycost};
    // <ps_partkey, ps_supplycost>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "p1";
    //  ================================================构建HashAgg================================================
    std::vector<int> group_set = {0}; // GroupBy字段
    std::vector<int> agg_set = {1}; // 聚合字段
    std::vector<int> star_bitmap = {0}; // 对应字段是否为 ‘*’ 表
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::MIN };
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建Scan================================================
    // <r_regionkey, r_name>
    std::shared_ptr<PhysicalTableScan> scan_region2 = std::make_shared<PhysicalTableScan>(table_region, -1, region_ids);

    std::vector<int> nation_ids2 = {0, 1, 2};
    // <n_nationkey, n_name, n_regionkey>
    std::shared_ptr<PhysicalTableScan> scan_nation2 = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids2);

    // <s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment>
    std::shared_ptr<PhysicalTableScan> scan_supplier2 = std::make_shared<PhysicalTableScan>(table_supplier);

    //  ================================================构建Filter-region2================================================
    std::shared_ptr<BoundColumnRefExpression> left_r_name2 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundConstantExpression> right_r_name2 = std::make_shared<BoundConstantExpression>(value_ASIA);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_r_name2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_r_name2->SetLeft(left_r_name2);
    comparisonExpression_r_name2->SetRight(right_r_name2);
    std::shared_ptr<PhysicalFilter> filter_region2 = std::make_shared<PhysicalFilter>(comparisonExpression_r_name2);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids4 = {2};
    std::vector<int> prode_ids4 = {0};
    // <r_regionkey, r_name, n_nationkey, n_name, n_regionkey>
    std::shared_ptr<PhysicalHashJoin> nation_join_region2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);

    std::vector<int> build_ids5 = {3};
    std::vector<int> prode_ids5 = {2};
    // <r_regionkey, r_name, n_nationkey, n_name, n_regionkey, s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment>
    std::shared_ptr<PhysicalHashJoin> suppliers_join_last2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids5, prode_ids5);

    //  ================================================构建Scan================================================
    std::vector<int> part_ids2 = {0, 2, 4, 5};
    // <p_partkey, p_mfgr, p_type, p_size>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids2);

    //  ================================================构建Filter-part================================================
    std::shared_ptr<BoundColumnRefExpression> left_p_size = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_15(25);
    std::shared_ptr<BoundConstantExpression> right_p_constant = std::make_shared<BoundConstantExpression>(value_15);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_p_size = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_p_size->SetLeft(left_p_size);
    comparisonExpression_p_size->SetRight(right_p_constant);
    // <p_partkey, p_mfgr, p_type, p_size>
    std::shared_ptr<PhysicalFilter> filter_part = std::make_shared<PhysicalFilter>(comparisonExpression_p_size);
    filter_part->exp_name = "1";

    std::string like_pattern = "%BRASS";
    ScalarFunction bound_function = LikeFun::GetLikeFunction();
    std::shared_ptr<BoundColumnRefExpression> left_p_type = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);
    Value value_BRASS(like_pattern);
    std::shared_ptr<BoundConstantExpression> right_p_constant2 = std::make_shared<BoundConstantExpression>(value_BRASS);
    std::vector<std::shared_ptr<Expression>> arguments_part;
    arguments_part.push_back(std::move(left_p_type));
    arguments_part.push_back(std::move(right_p_constant2));
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments_part, nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);
    // <p_partkey, p_mfgr, p_type, p_size>
    std::shared_ptr<PhysicalFilter> filter_part_type = std::make_shared<PhysicalFilter>(functionExpression);
    filter_part_type->exp_name = "2";
    //  ================================================构建Project-2================================================
    std::shared_ptr<BoundColumnRefExpression> p2_p_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_p_mfgr = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_p_partkey, p2_p_mfgr};
    // <p_partkey, p_mfgr>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);

    //  ================================================构建Scan================================================
    // <ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalTableScan> scan_partsupp2 = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids6 = {0};
    std::vector<int> prode_ids6 = {0};
    // <p_partkey, p_mfgr, ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalHashJoin> partsupp_join_last2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids6, prode_ids6);

    std::vector<int> build_ids7 = {3};
    std::vector<int> prode_ids7 = {5};
    // <r_regionkey, r_name, n_nationkey, n_name, n_regionkey, s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment, p_partkey, p_mfgr, ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalHashJoin> partsupp_join_suppliers = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids7, prode_ids7);

    std::vector<int> build_ids8 = {0};
    std::vector<int> prode_ids8 = {12};
    // <r_regionkey, r_name, n_nationkey, n_name, n_regionkey, s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment, p_partkey, p_mfgr, ps_partkey, ps_suppkey, ps_supplycost, min(ps_supplycost)>
    std::shared_ptr<PhysicalHashJoin> partsupp_join_suppliers_last = std::make_shared<PhysicalHashJoin>(JoinTypes::LEFT, build_ids8, prode_ids8);

    //  ================================================构建Filter-join================================================
    std::shared_ptr<BoundColumnRefExpression> left_min_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 18, 0);
    std::shared_ptr<BoundColumnRefExpression> right_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 16, 0);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_ps_supplycost = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_ps_supplycost->SetLeft(left_min_ps_supplycost);
    comparisonExpression_ps_supplycost->SetRight(right_ps_supplycost);
    std::shared_ptr<PhysicalFilter> filter_join = std::make_shared<PhysicalFilter>(comparisonExpression_ps_supplycost);
    //  ================================================构建Project-3================================================
    std::shared_ptr<BoundColumnRefExpression> p3_s_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 10, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_s_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_p_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 12, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_p_mfgr = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 13, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_s_address = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 7, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_s_phone = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 9, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_s_comment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 11, 0);
    std::vector<std::shared_ptr<Expression>> p3_expressions = {p3_s_acctbal, p3_s_name, p3_n_name, p3_p_partkey, p3_p_mfgr, p3_s_address, p3_s_phone, p3_s_comment};
    // <s_acctbal, s_name, n_name, p_partkey, p_mfgr, s_address, s_phone, s_comment>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0, 2, 1, 3};
    std::vector<LogicalType> key_types = {LogicalType::FLOAT, LogicalType::STRING, LogicalType::STRING, LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING, SortOrder::ASCENDING, SortOrder::ASCENDING, SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(project3);
    project3->AddChild(filter_join);
    filter_join->AddChild(partsupp_join_suppliers_last);
    partsupp_join_suppliers_last->AddChild(hashAgg);
    partsupp_join_suppliers_last->AddChild(partsupp_join_suppliers);
    hashAgg->AddChild(project1);
    project1->AddChild(partsupp_join_last);
    partsupp_join_last->AddChild(scan_partsupp);
    partsupp_join_last->AddChild(suppliers_join_last);
    suppliers_join_last->AddChild(scan_supplier);
    suppliers_join_last->AddChild(nation_join_region);
    nation_join_region->AddChild(scan_nation);
    nation_join_region->AddChild(filter_region);
    filter_region->AddChild(scan_region);
    partsupp_join_suppliers->AddChild(partsupp_join_last2);
    partsupp_join_suppliers->AddChild(suppliers_join_last2);
    partsupp_join_last2->AddChild(scan_partsupp2);
    partsupp_join_last2->AddChild(project2);
    project2->AddChild(filter_part_type);
    filter_part_type->AddChild(filter_part);
    filter_part->AddChild(scan_part);
    suppliers_join_last2->AddChild(scan_supplier2);
    suppliers_join_last2->AddChild(nation_join_region2);
    nation_join_region2->AddChild(scan_nation2);
    nation_join_region2->AddChild(filter_region2);
    filter_region2->AddChild(scan_region2);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q2执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q2查询
TEST(TPCHTest, Q2FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    std::vector<std::string> nation_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "nation.tbl_" + std::to_string(i);
        nation_file_names.emplace_back(file_name);
    }
    InsertNationMul(table_nation, scheduler, work_ids, partition_idxs, nation_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 插入Region表数据
    std::shared_ptr<Table> table_region;
    std::vector<std::string> region_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "region.tbl_" + std::to_string(i);
        region_file_names.emplace_back(file_name);
    }
    InsertRegionMul(table_region, scheduler, work_ids, partition_idxs, region_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 插入Partsupp表数据
    std::shared_ptr<Table> table_partsupp;
    std::vector<std::string> partsupp_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "partsupp.tbl_" + std::to_string(i);
        partsupp_file_names.emplace_back(file_name);
    }
    InsertPartsuppMul(table_partsupp, scheduler, work_ids, partition_idxs, partsupp_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    std::vector<std::string> part_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "part.tbl_" + std::to_string(i);
        part_file_names.emplace_back(file_name);
    }
    InsertPartMul(table_part, scheduler, work_ids, partition_idxs, part_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    std::vector<std::string> supplier_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "supplier.tbl_" + std::to_string(i);
        supplier_file_names.emplace_back(file_name);
    }
    InsertSupplierMul(table_supplier, scheduler, work_ids, partition_idxs, supplier_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    //  ================================================构建Scan================================================
    std::vector<int> region_ids = {0, 1};
    // <r_regionkey, r_name>
    std::shared_ptr<PhysicalTableScan> scan_region = std::make_shared<PhysicalTableScan>(table_region, -1, region_ids);

    std::vector<int> nation_ids = {0, 2};
    // <n_nationkey, n_regionkey>
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> supplier_ids = {0, 3};
    // <s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    std::vector<int> partsupp_ids = {0, 1, 3};
    // <ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalTableScan> scan_partsupp = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);
    //  ================================================构建Filter-region================================================
    std::shared_ptr<BoundColumnRefExpression> left_r_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_ASIA("ASIA");
    std::shared_ptr<BoundConstantExpression> right_r_name = std::make_shared<BoundConstantExpression>(value_ASIA);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_r_name = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_r_name->SetLeft(left_r_name);
    comparisonExpression_r_name->SetRight(right_r_name);
    std::shared_ptr<PhysicalFilter> filter_region = std::make_shared<PhysicalFilter>(comparisonExpression_r_name);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {1};
    std::vector<int> prode_ids1 = {0};
    // <r_regionkey, r_name, l.n_nationkey, l.n_regionkey>
    std::shared_ptr<PhysicalHashJoin> nation_join_region = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);

    std::vector<int> build_ids2 = {1};
    std::vector<int> prode_ids2 = {2};
    // <r_regionkey, r_name, l.n_nationkey, l.n_regionkey, s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalHashJoin> suppliers_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);

    std::vector<int> build_ids3 = {1};
    std::vector<int> prode_ids3 = {4};
    // <r_regionkey, r_name, l.n_nationkey, l.n_regionkey, s_suppkey, s_nationkey, ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalHashJoin> partsupp_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    partsupp_join_last->exp_name = "22";
    //  ================================================构建Project-1================================================
    std::shared_ptr<BoundColumnRefExpression> p1_ps_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 8, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_ps_partkey, p1_ps_supplycost};
    // <ps_partkey, ps_supplycost>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "p1";
    //  ================================================构建HashAgg================================================
    std::vector<int> group_set = {0}; // GroupBy字段
    std::vector<int> agg_set = {1}; // 聚合字段
    std::vector<int> star_bitmap = {0}; // 对应字段是否为 ‘*’ 表
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::MIN };
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建Scan================================================
    // <r_regionkey, r_name>
    std::shared_ptr<PhysicalTableScan> scan_region2 = std::make_shared<PhysicalTableScan>(table_region, -1, region_ids);

    std::vector<int> nation_ids2 = {0, 1, 2};
    // <n_nationkey, n_name, n_regionkey>
    std::shared_ptr<PhysicalTableScan> scan_nation2 = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids2);

    // <s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment>
    std::shared_ptr<PhysicalTableScan> scan_supplier2 = std::make_shared<PhysicalTableScan>(table_supplier);

    //  ================================================构建Filter-region2================================================
    std::shared_ptr<BoundColumnRefExpression> left_r_name2 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundConstantExpression> right_r_name2 = std::make_shared<BoundConstantExpression>(value_ASIA);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_r_name2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_r_name2->SetLeft(left_r_name2);
    comparisonExpression_r_name2->SetRight(right_r_name2);
    std::shared_ptr<PhysicalFilter> filter_region2 = std::make_shared<PhysicalFilter>(comparisonExpression_r_name2);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids4 = {2};
    std::vector<int> prode_ids4 = {0};
    // <r_regionkey, r_name, n_nationkey, n_name, n_regionkey>
    std::shared_ptr<PhysicalHashJoin> nation_join_region2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);

    std::vector<int> build_ids5 = {3};
    std::vector<int> prode_ids5 = {2};
    // <r_regionkey, r_name, n_nationkey, n_name, n_regionkey, s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment>
    std::shared_ptr<PhysicalHashJoin> suppliers_join_last2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids5, prode_ids5);

    //  ================================================构建Scan================================================
    std::vector<int> part_ids2 = {0, 2, 4, 5};
    // <p_partkey, p_mfgr, p_type, p_size>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids2);

    //  ================================================构建Filter-part================================================
    std::shared_ptr<BoundColumnRefExpression> left_p_size = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_15(25);
    std::shared_ptr<BoundConstantExpression> right_p_constant = std::make_shared<BoundConstantExpression>(value_15);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_p_size = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_p_size->SetLeft(left_p_size);
    comparisonExpression_p_size->SetRight(right_p_constant);
    // <p_partkey, p_mfgr, p_type, p_size>
    std::shared_ptr<PhysicalFilter> filter_part = std::make_shared<PhysicalFilter>(comparisonExpression_p_size);
    filter_part->exp_name = "1";
    std::string like_pattern = "%BRASS";
    ScalarFunction bound_function = LikeFun::GetLikeFunction();
    std::shared_ptr<BoundColumnRefExpression> left_p_type = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);
    Value value_BRASS(like_pattern);
    std::shared_ptr<BoundConstantExpression> right_p_constant2 = std::make_shared<BoundConstantExpression>(value_BRASS);
    std::vector<std::shared_ptr<Expression>> arguments_part;
    arguments_part.push_back(std::move(left_p_type));
    arguments_part.push_back(std::move(right_p_constant2));
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments_part, nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);
    // <p_partkey, p_mfgr, p_type, p_size>
    std::shared_ptr<PhysicalFilter> filter_part_type = std::make_shared<PhysicalFilter>(functionExpression);
    filter_part_type->exp_name = "2";
    //  ================================================构建Project-2================================================
    std::shared_ptr<BoundColumnRefExpression> p2_p_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_p_mfgr = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_p_partkey, p2_p_mfgr};
    // <p_partkey, p_mfgr>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);

    //  ================================================构建Scan================================================
    // <ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalTableScan> scan_partsupp2 = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids6 = {0};
    std::vector<int> prode_ids6 = {0};
    // <p_partkey, p_mfgr, ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalHashJoin> partsupp_join_last2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids6, prode_ids6);

    std::vector<int> build_ids7 = {3};
    std::vector<int> prode_ids7 = {5};
    // <r_regionkey, r_name, n_nationkey, n_name, n_regionkey, s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment, p_partkey, p_mfgr, ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalHashJoin> partsupp_join_suppliers = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids7, prode_ids7);

    std::vector<int> build_ids8 = {0};
    std::vector<int> prode_ids8 = {12};
    // <r_regionkey, r_name, n_nationkey, n_name, n_regionkey, s_suppkey, s_name, s_address, s_nationkey, s_phone, s_acctbal, s_comment, p_partkey, p_mfgr, ps_partkey, ps_suppkey, ps_supplycost, min(ps_supplycost)>
    std::shared_ptr<PhysicalHashJoin> partsupp_join_suppliers_last = std::make_shared<PhysicalHashJoin>(JoinTypes::LEFT, build_ids8, prode_ids8);

    //  ================================================构建Filter-join================================================
    std::shared_ptr<BoundColumnRefExpression> left_min_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 18, 0);
    std::shared_ptr<BoundColumnRefExpression> right_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 16, 0);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_ps_supplycost = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_ps_supplycost->SetLeft(left_min_ps_supplycost);
    comparisonExpression_ps_supplycost->SetRight(right_ps_supplycost);
    std::shared_ptr<PhysicalFilter> filter_join = std::make_shared<PhysicalFilter>(comparisonExpression_ps_supplycost);

    //  ================================================构建Project-3================================================
    std::shared_ptr<BoundColumnRefExpression> p3_s_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 10, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_s_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_p_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 12, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_p_mfgr = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 13, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_s_address = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 7, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_s_phone = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 9, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_s_comment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 11, 0);
    std::vector<std::shared_ptr<Expression>> p3_expressions = {p3_s_acctbal, p3_s_name, p3_n_name, p3_p_partkey, p3_p_mfgr, p3_s_address, p3_s_phone, p3_s_comment};
    // <s_acctbal, s_name, n_name, p_partkey, p_mfgr, s_address, s_phone, s_comment>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0, 2, 1, 3};
    std::vector<LogicalType> key_types = {LogicalType::FLOAT, LogicalType::STRING, LogicalType::STRING, LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING, SortOrder::ASCENDING, SortOrder::ASCENDING, SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(project3);
    project3->AddChild(filter_join);
    filter_join->AddChild(partsupp_join_suppliers_last);
    partsupp_join_suppliers_last->AddChild(hashAgg);
    partsupp_join_suppliers_last->AddChild(partsupp_join_suppliers);
    hashAgg->AddChild(project1);
    project1->AddChild(partsupp_join_last);
    partsupp_join_last->AddChild(scan_partsupp);
    partsupp_join_last->AddChild(suppliers_join_last);
    suppliers_join_last->AddChild(scan_supplier);
    suppliers_join_last->AddChild(nation_join_region);
    nation_join_region->AddChild(scan_nation);
    nation_join_region->AddChild(filter_region);
    filter_region->AddChild(scan_region);
    partsupp_join_suppliers->AddChild(partsupp_join_last2);
    partsupp_join_suppliers->AddChild(suppliers_join_last2);
    partsupp_join_last2->AddChild(scan_partsupp2);
    partsupp_join_last2->AddChild(project2);
    project2->AddChild(filter_part_type);
    filter_part_type->AddChild(filter_part);
    filter_part->AddChild(scan_part);
    suppliers_join_last2->AddChild(scan_supplier2);
    suppliers_join_last2->AddChild(nation_join_region2);
    nation_join_region2->AddChild(scan_nation2);
    nation_join_region2->AddChild(filter_region2);
    filter_region2->AddChild(scan_region2);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q2执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q3=============================
// 测试单线程Q3查询
TEST(TPCHTest, Q3SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    InsertCustomer(table_customer, scheduler);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    InsertOrders(table_orders, scheduler);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));

    //  ================================================构建Scan================================================
    std::vector<int> customer_ids = {0, 6};
    // <c_custkey, c_mktsegment>
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> orders_ids = {0, 1, 4, 7};
    // <o_orderkey, o_custkey, o_orderdate, o_shippriority>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    std::vector<int> lineitem_ids = {0, 5, 6, 10};
    // <l_orderkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    //  ================================================构建Filter-customer================================================
    std::shared_ptr<BoundColumnRefExpression> left_c_mktsegment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_BUILDING("BUILDING");
    std::shared_ptr<BoundConstantExpression> right_c_mktsegment = std::make_shared<BoundConstantExpression>(value_BUILDING);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_c_mktsegment = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_c_mktsegment->SetLeft(left_c_mktsegment);
    comparisonExpression_c_mktsegment->SetRight(right_c_mktsegment);

    std::shared_ptr<BoundColumnRefExpression> left_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    Value value_14999(14999);
    std::shared_ptr<BoundConstantExpression> right_c_custkey = std::make_shared<BoundConstantExpression>(value_14999);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_c_custkey = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_c_custkey->SetLeft(left_c_custkey);
    comparisonExpression_c_custkey->SetRight(right_c_custkey);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_customer = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_c_mktsegment, comparisonExpression_c_custkey);
    std::shared_ptr<PhysicalFilter> filter_customer = std::make_shared<PhysicalFilter>(conjunctionExpression_customer);

    //  ================================================构建Filter-orders================================================
    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_795196800(795196800);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate = std::make_shared<BoundConstantExpression>(value_795196800);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_o_orderdate->SetLeft(left_o_orderdate);
    comparisonExpression_o_orderdate->SetRight(right_o_orderdate);
    std::shared_ptr<PhysicalFilter> filter_orders = std::make_shared<PhysicalFilter>(comparisonExpression_o_orderdate);

    //  ================================================构建Filter-Lineitem================================================
    std::shared_ptr<BoundColumnRefExpression> left_l_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    std::shared_ptr<BoundConstantExpression> right_l_shipdate = std::make_shared<BoundConstantExpression>(value_795196800);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHAN);
    comparisonExpression_l_shipdate->SetLeft(left_l_shipdate);
    comparisonExpression_l_shipdate->SetRight(right_l_shipdate);
    std::shared_ptr<PhysicalFilter> filter_lineitem = std::make_shared<PhysicalFilter>(comparisonExpression_l_shipdate);

    //  ================================================构建HashJoin ===================================================
    // Orders join Customer
    std::vector<int> build_ids1 = {1};
    std::vector<int> prode_ids1 = {0};
    // <c_custkey, c_mktsegment, o_orderkey, o_custkey, o_orderdate, o_shippriority>
    std::shared_ptr<PhysicalHashJoin> orders_join_customer = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);

    // Lineitem join Last
    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {2};
    // <c_custkey, c_mktsegment, o_orderkey, o_custkey, o_orderdate, o_shippriority, l_orderkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalHashJoin> lineitem_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p_l_orderkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);

    std::shared_ptr<BoundColumnRefExpression> l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 8, 0);
    Value value_1F(1.0F);
    std::shared_ptr<BoundConstantExpression> l_constant_1 = std::make_shared<BoundConstantExpression>(value_1F);
    std::vector<LogicalType> arguments_type1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p sub_function = GetSubFunction();
    ScalarProjectFunction bound_sub_function("-", arguments_type1, LogicalType::FLOAT, sub_function, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions1 = {l_constant_1, l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> l_discount_sub_1 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_sub_function, expressions1, nullptr);
    l_discount_sub_1->alias = "(1.00 - l_discount)";

    std::shared_ptr<BoundColumnRefExpression> l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 7, 0);
    std::vector<LogicalType> arguments_type2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p mul_function = GetMulFunction();
    ScalarProjectFunction bound_mul_function("*", arguments_type2, LogicalType::FLOAT, mul_function, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions2 = {l_extendedprice, l_discount_sub_1};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_mul_function, expressions2, nullptr);
    extendedprice_discount_col->alias = "l_extendedprice * (1.00 - l_discount)";

    std::shared_ptr<BoundColumnRefExpression> p_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 4, 0);
    std::shared_ptr<BoundColumnRefExpression> p_o_shippriority = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 5, 0);
    std::vector<std::shared_ptr<Expression>> p_expressions = {p_l_orderkey, extendedprice_discount_col, p_o_orderdate, p_o_shippriority};
    // <l_orderkey, l_extendedprice*(1-l_discount), o_orderdate, o_shippriority>
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(p_expressions);

    //  ================================================构建HashAgg================================================
    std::vector<int> group_set = {0, 2, 3}; // GroupBy字段
    std::vector<int> agg_set = {1}; // 聚合字段
    std::vector<int> star_bitmap = {0}; // 对应字段是否为 ‘*’ 表
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::SUM };
    // <l_orderkey, o_orderdate, o_shippriority, Sum(l_extendedprice*(1-l_discount))>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {3, 1};
    std::vector<LogicalType> key_types = {LogicalType::DOUBLE, LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING, SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project);
    project->AddChild(lineitem_join_last);
    lineitem_join_last->AddChild(filter_lineitem);
    lineitem_join_last->AddChild(orders_join_customer);
    filter_lineitem->AddChild(scan_lineitem);
    orders_join_customer->AddChild(filter_orders);
    orders_join_customer->AddChild(filter_customer);
    filter_orders->AddChild(scan_orders);
    filter_customer->AddChild(scan_customer);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q2执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q3查询
TEST(TPCHTest, Q3FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    std::vector<std::string> customer_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "customer.tbl_" + std::to_string(i);
        customer_file_names.emplace_back(file_name);
    }
    InsertCustomerMul(table_customer, scheduler, work_ids, partition_idxs, customer_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));

    //  ================================================构建Scan================================================
    std::vector<int> customer_ids = {0, 6};
    // <c_custkey, c_mktsegment>
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> orders_ids = {0, 1, 4, 7};
    // <o_orderkey, o_custkey, o_orderdate, o_shippriority>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    std::vector<int> lineitem_ids = {0, 5, 6, 10};
    // <l_orderkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    //  ================================================构建Filter-customer================================================
    std::shared_ptr<BoundColumnRefExpression> left_c_mktsegment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_BUILDING("BUILDING");
    std::shared_ptr<BoundConstantExpression> right_c_mktsegment = std::make_shared<BoundConstantExpression>(value_BUILDING);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_c_mktsegment = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_c_mktsegment->SetLeft(left_c_mktsegment);
    comparisonExpression_c_mktsegment->SetRight(right_c_mktsegment);

    std::shared_ptr<BoundColumnRefExpression> left_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    Value value_14999(14999);
    std::shared_ptr<BoundConstantExpression> right_c_custkey = std::make_shared<BoundConstantExpression>(value_14999);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_c_custkey = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_c_custkey->SetLeft(left_c_custkey);
    comparisonExpression_c_custkey->SetRight(right_c_custkey);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_customer = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_c_mktsegment, comparisonExpression_c_custkey);
    std::shared_ptr<PhysicalFilter> filter_customer = std::make_shared<PhysicalFilter>(conjunctionExpression_customer);

    //  ================================================构建Filter-orders================================================
    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_795196800(795196800);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate = std::make_shared<BoundConstantExpression>(value_795196800);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_o_orderdate->SetLeft(left_o_orderdate);
    comparisonExpression_o_orderdate->SetRight(right_o_orderdate);
    std::shared_ptr<PhysicalFilter> filter_orders = std::make_shared<PhysicalFilter>(comparisonExpression_o_orderdate);

    //  ================================================构建Filter-Lineitem================================================
    std::shared_ptr<BoundColumnRefExpression> left_l_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    std::shared_ptr<BoundConstantExpression> right_l_shipdate = std::make_shared<BoundConstantExpression>(value_795196800);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHAN);
    comparisonExpression_l_shipdate->SetLeft(left_l_shipdate);
    comparisonExpression_l_shipdate->SetRight(right_l_shipdate);
    std::shared_ptr<PhysicalFilter> filter_lineitem = std::make_shared<PhysicalFilter>(comparisonExpression_l_shipdate);

    //  ================================================构建HashJoin ===================================================
    // Orders join Customer
    std::vector<int> build_ids1 = {1};
    std::vector<int> prode_ids1 = {0};
    // <c_custkey, c_mktsegment, o_orderkey, o_custkey, o_orderdate, o_shippriority>
    std::shared_ptr<PhysicalHashJoin> orders_join_customer = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);

    // Lineitem join Last
    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {2};
    // <c_custkey, c_mktsegment, o_orderkey, o_custkey, o_orderdate, o_shippriority, l_orderkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalHashJoin> lineitem_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p_l_orderkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);

    std::shared_ptr<BoundColumnRefExpression> l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 8, 0);
    Value value_1F(1.0F);
    std::shared_ptr<BoundConstantExpression> l_constant_1 = std::make_shared<BoundConstantExpression>(value_1F);
    std::vector<LogicalType> arguments_type1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p sub_function = GetSubFunction();
    ScalarProjectFunction bound_sub_function("-", arguments_type1, LogicalType::FLOAT, sub_function, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions1 = {l_constant_1, l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> l_discount_sub_1 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_sub_function, expressions1, nullptr);
    l_discount_sub_1->alias = "(1.00 - l_discount)";

    std::shared_ptr<BoundColumnRefExpression> l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 7, 0);
    std::vector<LogicalType> arguments_type2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p mul_function = GetMulFunction();
    ScalarProjectFunction bound_mul_function("*", arguments_type2, LogicalType::FLOAT, mul_function, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions2 = {l_extendedprice, l_discount_sub_1};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_mul_function, expressions2, nullptr);
    extendedprice_discount_col->alias = "l_extendedprice * (1.00 - l_discount)";

    std::shared_ptr<BoundColumnRefExpression> p_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 4, 0);
    std::shared_ptr<BoundColumnRefExpression> p_o_shippriority = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 5, 0);
    std::vector<std::shared_ptr<Expression>> p_expressions = {p_l_orderkey, extendedprice_discount_col, p_o_orderdate, p_o_shippriority};
    // <l_orderkey, l_extendedprice*(1-l_discount), o_orderdate, o_shippriority>
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(p_expressions);

    //  ================================================构建HashAgg================================================
    std::vector<int> group_set = {0, 2, 3}; // GroupBy字段
    std::vector<int> agg_set = {1}; // 聚合字段
    std::vector<int> star_bitmap = {0}; // 对应字段是否为 ‘*’ 表
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::SUM };
    // <l_orderkey, o_orderdate, o_shippriority, Sum(l_extendedprice*(1-l_discount))>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {3, 1};
    std::vector<LogicalType> key_types = {LogicalType::DOUBLE, LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING, SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project);
    project->AddChild(lineitem_join_last);
    lineitem_join_last->AddChild(filter_lineitem);
    lineitem_join_last->AddChild(orders_join_customer);
    filter_lineitem->AddChild(scan_lineitem);
    orders_join_customer->AddChild(filter_orders);
    orders_join_customer->AddChild(filter_customer);
    filter_orders->AddChild(scan_orders);
    filter_customer->AddChild(scan_customer);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q2执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q4=============================
// 测试单线程Q4查询
TEST(TPCHTest, Q4SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    InsertOrders(table_orders, scheduler);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));

    //  ================================================构建Scan================================================
    std::vector<int> orders_ids = {0, 4, 5};
    // <o_orderkey, o_orderdate, o_orderpriority>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    std::vector<int> lineitem_ids = {0, 11, 12};
    // <l_orderkey, l_commitdate, l_receiptdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    //  ================================================构建Filter-orders================================================
    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    Value value_741456000(741456000);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate = std::make_shared<BoundConstantExpression>(value_741456000);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_o_orderdate->SetLeft(left_o_orderdate);
    comparisonExpression_o_orderdate->SetRight(right_o_orderdate);

    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    Value value_749404800(749404800);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate2 = std::make_shared<BoundConstantExpression>(value_749404800);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_o_orderdate2->SetLeft(left_o_orderdate2);
    comparisonExpression_o_orderdate2->SetRight(right_o_orderdate2);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_orders = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_o_orderdate, comparisonExpression_o_orderdate2);
    std::shared_ptr<PhysicalFilter> filter_orders = std::make_shared<PhysicalFilter>(conjunctionExpression_orders);
    filter_orders->exp_name = "3";
    //  ================================================构建Filter-Lineitem================================================
    std::shared_ptr<BoundColumnRefExpression> left_l_commitdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> right_l_receiptdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_commitdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_commitdate->SetLeft(left_l_commitdate);
    comparisonExpression_l_commitdate->SetRight(right_l_receiptdate);
    std::shared_ptr<PhysicalFilter> filter_lineitem = std::make_shared<PhysicalFilter>(comparisonExpression_l_commitdate);

    //  ================================================构建HashJoin ===================================================
    // Orders join Lineitem
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {0};
    // <o_orderkey, o_orderdate, o_orderpriority>
    std::shared_ptr<PhysicalHashJoin> orders_join_lineitem = std::make_shared<PhysicalHashJoin>(JoinTypes::SEMI, build_ids1, prode_ids1);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p_o_orderpriority = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::vector<std::shared_ptr<Expression>> p_expressions = {p_o_orderpriority};
    // <o_orderpriority>
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(p_expressions);

    //  ================================================构建HashAgg================================================
    std::vector<int> group_set = {0}; // GroupBy字段
    std::vector<int> agg_set = {0}; // 聚合字段
    std::vector<int> star_bitmap = {0}; // 对应字段是否为 ‘*’ 表
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::COUNT };
    // <o_orderpriority, Count(*)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::STRING};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project);
    project->AddChild(orders_join_lineitem);
    orders_join_lineitem->AddChild(filter_lineitem);
    orders_join_lineitem->AddChild(filter_orders);
    filter_orders->AddChild(scan_orders);
    filter_lineitem->AddChild(scan_lineitem);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q2执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q4查询
TEST(TPCHTest, Q4FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));

    //  ================================================构建Scan================================================
    std::vector<int> orders_ids = {0, 4, 5};
    // <o_orderkey, o_orderdate, o_orderpriority>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    std::vector<int> lineitem_ids = {0, 11, 12};
    // <l_orderkey, l_commitdate, l_receiptdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    //  ================================================构建Filter-orders================================================
    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    Value value_741456000(741456000);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate = std::make_shared<BoundConstantExpression>(value_741456000);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_o_orderdate->SetLeft(left_o_orderdate);
    comparisonExpression_o_orderdate->SetRight(right_o_orderdate);

    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    Value value_749404800(749404800);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate2 = std::make_shared<BoundConstantExpression>(value_749404800);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_o_orderdate2->SetLeft(left_o_orderdate2);
    comparisonExpression_o_orderdate2->SetRight(right_o_orderdate2);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_orders = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_o_orderdate, comparisonExpression_o_orderdate2);
    std::shared_ptr<PhysicalFilter> filter_orders = std::make_shared<PhysicalFilter>(conjunctionExpression_orders);
    filter_orders->exp_name = "3";
    //  ================================================构建Filter-Lineitem================================================
    std::shared_ptr<BoundColumnRefExpression> left_l_commitdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> right_l_receiptdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_commitdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_commitdate->SetLeft(left_l_commitdate);
    comparisonExpression_l_commitdate->SetRight(right_l_receiptdate);
    std::shared_ptr<PhysicalFilter> filter_lineitem = std::make_shared<PhysicalFilter>(comparisonExpression_l_commitdate);

    //  ================================================构建HashJoin ===================================================
    // Orders join Lineitem
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {0};
    // <o_orderkey, o_orderdate, o_orderpriority>
    std::shared_ptr<PhysicalHashJoin> orders_join_lineitem = std::make_shared<PhysicalHashJoin>(JoinTypes::SEMI, build_ids1, prode_ids1);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p_o_orderpriority = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::vector<std::shared_ptr<Expression>> p_expressions = {p_o_orderpriority};
    // <o_orderpriority>
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(p_expressions);

    //  ================================================构建HashAgg================================================
    std::vector<int> group_set = {0}; // GroupBy字段
    std::vector<int> agg_set = {0}; // 聚合字段
    std::vector<int> star_bitmap = {0}; // 对应字段是否为 ‘*’ 表
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::COUNT };
    // <o_orderpriority, Count(*)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::STRING};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project);
    project->AddChild(orders_join_lineitem);
    orders_join_lineitem->AddChild(filter_lineitem);
    orders_join_lineitem->AddChild(filter_orders);
    filter_orders->AddChild(scan_orders);
    filter_lineitem->AddChild(scan_lineitem);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q2执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q5=============================
// 测试Q5Pipeline构建
TEST(TPCHTest, Q5PipelineBuildTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    InsertNation(table_nation, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Region表数据
    std::shared_ptr<Table> table_region;
    InsertRegion(table_region, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertRegion Finish!!!", __FILE__, __LINE__);

    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    InsertCustomer(table_customer, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    InsertOrders(table_orders, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    InsertSupplier(table_supplier, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> region_ids = {0, 1};
    std::shared_ptr<PhysicalTableScan> scan_region = std::make_shared<PhysicalTableScan>(table_region, -1, region_ids);

    std::vector<int> nation_ids = {0, 1, 2};
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> customer_ids = {0, 3};
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> orders_ids = {0, 1, 4};
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    std::vector<int> lineitem_ids = {0, 2, 5, 6};
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> supplier_ids = {0, 3};
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    //  ================================================构建Filter-1================================================
    std::shared_ptr<BoundColumnRefExpression> left_r_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_ASIA("ASIA");
    std::shared_ptr<BoundConstantExpression> right_r_name = std::make_shared<BoundConstantExpression>(value_ASIA);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_r_name = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_r_name->SetLeft(left_r_name);
    comparisonExpression_r_name->SetRight(right_r_name);
    std::shared_ptr<PhysicalFilter> filter_region = std::make_shared<PhysicalFilter>(comparisonExpression_r_name);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {2};
    std::vector<int> prode_ids1 = {0};
    // <r_regionkey, r_name, l.n_nationkey, l.n_name, l.n_regionkey>
    std::shared_ptr<PhysicalHashJoin> nation_join_region = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);

    std::vector<int> build_ids2 = {1};
    std::vector<int> prode_ids2 = {2};
    // <r_regionkey, r_name, l.n_nationkey, l.n_name, l.n_regionkey, l.c_custkey, l.c_nationkey>
    std::shared_ptr<PhysicalHashJoin> customer_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);

    //  ================================================构建Filter2================================================
    std::shared_ptr<BoundColumnRefExpression> left_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    Value value_14999(14999);
    std::shared_ptr<BoundConstantExpression> right_c_custkey = std::make_shared<BoundConstantExpression>(value_14999);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_c_custkey = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_c_custkey->SetLeft(left_c_custkey);
    comparisonExpression_c_custkey->SetRight(right_c_custkey);
    std::shared_ptr<PhysicalFilter> filter_custkey = std::make_shared<PhysicalFilter>(comparisonExpression_c_custkey);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids3 = {1};
    std::vector<int> prode_ids3 = {5};
    // <r_regionkey, r_name, l.n_nationkey, l.n_name, l.n_regionkey, l.c_custkey, l.c_nationkey, l.o_orderkey, l.o_custkey, l.o_orderdate>
    std::shared_ptr<PhysicalHashJoin> orders_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);

    std::vector<int> build_ids4 = {0};
    std::vector<int> prode_ids4 = {7};
    // <l_orderkey, l_suppkey, l_extendedprice, l_discount, o_orderkey, o_custkey, o_orderdate, c_custkey, c_nationkey, n_nationkey, n_name, n_regionkey, r_regionkey, r_name>
    std::shared_ptr<PhysicalHashJoin> lineitem_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);

    std::vector<int> build_ids5 = {2, 6, 11};
    std::vector<int> prode_ids5 = {1, 1, 0};
    // <r_regionkey, r_name, l.n_nationkey, l.n_name, l.n_regionkey, l.c_custkey, l.c_nationkey, l.o_orderkey, l.o_custkey, l.o_orderdate, l.l_orderkey, l.l_suppkey, l.l_extendedprice, l.l_discount>
    std::shared_ptr<PhysicalHashJoin> last_join_supplier = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids5, prode_ids5);

    //  ================================================构建Filter-3================================================
    //  =======================================表达1=======================================
    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_820425600(820425600); // 1996-01-01
    std::shared_ptr<BoundConstantExpression> right_o_orderdate = std::make_shared<BoundConstantExpression>(value_820425600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_o_orderdate->SetLeft(left_o_orderdate);
    comparisonExpression_o_orderdate->SetRight(right_o_orderdate);
    //  =======================================表达2=======================================
    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_852048000(852048000); // 1997-01-01
    std::shared_ptr<BoundConstantExpression> right_o_orderdate2 = std::make_shared<BoundConstantExpression>(value_852048000);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_o_orderdate2->SetLeft(left_o_orderdate2);
    comparisonExpression_o_orderdate2->SetRight(right_o_orderdate2);
    //  =======================================And表达=======================================
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_o_orderdate, comparisonExpression_o_orderdate2);
    std::shared_ptr<PhysicalFilter> filter_orders = std::make_shared<PhysicalFilter>(conjunctionExpression);

    //  ================================================构建Project-1================================================
    std::shared_ptr<BoundColumnRefExpression> p1_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 14, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 15, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_l_extendedprice, p1_l_discount, p1_n_name};
    // <l_extendedprice, l_discount, n_name>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);

    //  ================================================构建Project-2================================================
    std::shared_ptr<BoundColumnRefExpression> n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);

    Value value_1f(1.0f); // 1997-01-01
    std::shared_ptr<BoundConstantExpression> left_l_discount = std::make_shared<BoundConstantExpression>(value_1f);
    std::shared_ptr<BoundColumnRefExpression> right_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    scalar_function_p sub_function = GetSubFunction();
    std::vector<LogicalType> arguments_type1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    ScalarProjectFunction bound_sub_function("-", arguments_type1, LogicalType::FLOAT, sub_function, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions1 = {left_l_discount, right_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_sub_function, expressions1, nullptr);
    discount_1->alias = "1.00 - l_discount";

    std::shared_ptr<BoundColumnRefExpression> l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 0, 0);
    std::vector<LogicalType> arguments_type = { LogicalType::INTEGER, LogicalType::FLOAT };
    scalar_function_p mul_function = GetMulFunction();
    ScalarProjectFunction bound_mul_function("*", arguments_type, LogicalType::FLOAT, mul_function, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions2 = {l_extendedprice, discount_1};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_mul_function, expressions2, nullptr);
    extendedprice_discount_col->alias = "l_extendedprice * (1.00 - l_discount)";
    std::vector<std::shared_ptr<Expression>> expressions3 = {n_name, extendedprice_discount_col};

    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(expressions3);

    //  ================================================构建HashAgg================================================

    std::vector<int> group_set = {0};
    std::vector<int32_t> agg_set = {1};
    std::vector<int> star_bitmap = {0};
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::SUM };
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {1};
    std::vector<LogicalType> key_types = {LogicalType::DOUBLE};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project2);
    project2->AddChild(project1);
    project1->AddChild(last_join_supplier);
    last_join_supplier->AddChild(lineitem_join_last);
    last_join_supplier->AddChild(scan_supplier);
    lineitem_join_last->AddChild(scan_lineitem);
    lineitem_join_last->AddChild(orders_join_last);
    orders_join_last->AddChild(filter_orders);
    orders_join_last->AddChild(filter_custkey);
    filter_orders->AddChild(scan_orders);
    filter_custkey->AddChild(customer_join_last);
    customer_join_last->AddChild(scan_customer);
    customer_join_last->AddChild(nation_join_region);
    nation_join_region->AddChild(scan_nation);
    nation_join_region->AddChild(filter_region);
    filter_region->AddChild(scan_region);
    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q5执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试Q5Pipeline构建
TEST(TPCHTest, Q5FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    std::vector<std::string> nation_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "nation.tbl_" + std::to_string(i);
        nation_file_names.emplace_back(file_name);
    }
    InsertNationMul(table_nation, scheduler, work_ids, partition_idxs, nation_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 插入Region表数据
    std::shared_ptr<Table> table_region;
    std::vector<std::string> region_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "region.tbl_" + std::to_string(i);
        region_file_names.emplace_back(file_name);
    }
    InsertRegionMul(table_region, scheduler, work_ids, partition_idxs, region_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    std::vector<std::string> customer_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "customer.tbl_" + std::to_string(i);
        customer_file_names.emplace_back(file_name);
    }
    InsertCustomerMul(table_customer, scheduler, work_ids, partition_idxs, customer_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    std::vector<std::string> supplier_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "supplier.tbl_" + std::to_string(i);
        supplier_file_names.emplace_back(file_name);
    }
    InsertSupplierMul(table_supplier, scheduler, work_ids, partition_idxs, supplier_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] Import Data Finish!!!", __FILE__, __LINE__);
    //  ================================================构建Scan================================================
    std::vector<int> region_ids = {0, 1};
    std::shared_ptr<PhysicalTableScan> scan_region = std::make_shared<PhysicalTableScan>(table_region, -1, region_ids);

    std::vector<int> nation_ids = {0, 1, 2};
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> customer_ids = {0, 3};
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> orders_ids = {0, 1, 4};
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    std::vector<int> lineitem_ids = {0, 2, 5, 6};
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> supplier_ids = {0, 3};
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    //  ================================================构建Filter-1================================================
    std::shared_ptr<BoundColumnRefExpression> left_r_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_ASIA("ASIA");
    std::shared_ptr<BoundConstantExpression> right_r_name = std::make_shared<BoundConstantExpression>(value_ASIA);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_r_name = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_r_name->SetLeft(left_r_name);
    comparisonExpression_r_name->SetRight(right_r_name);
    std::shared_ptr<PhysicalFilter> filter_region = std::make_shared<PhysicalFilter>(comparisonExpression_r_name);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {2};
    std::vector<int> prode_ids1 = {0};
    // <r_regionkey, r_name, l.n_nationkey, l.n_name, l.n_regionkey>
    std::shared_ptr<PhysicalHashJoin> nation_join_region = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);

    std::vector<int> build_ids2 = {1};
    std::vector<int> prode_ids2 = {2};
    // <r_regionkey, r_name, l.n_nationkey, l.n_name, l.n_regionkey, l.c_custkey, l.c_nationkey>
    std::shared_ptr<PhysicalHashJoin> customer_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);

    //  ================================================构建Filter2================================================
    std::shared_ptr<BoundColumnRefExpression> left_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    Value value_14999(14999);
    std::shared_ptr<BoundConstantExpression> right_c_custkey = std::make_shared<BoundConstantExpression>(value_14999);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_c_custkey = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_c_custkey->SetLeft(left_c_custkey);
    comparisonExpression_c_custkey->SetRight(right_c_custkey);
    std::shared_ptr<PhysicalFilter> filter_custkey = std::make_shared<PhysicalFilter>(comparisonExpression_c_custkey);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids3 = {1};
    std::vector<int> prode_ids3 = {5};
    // <r_regionkey, r_name, l.n_nationkey, l.n_name, l.n_regionkey, l.c_custkey, l.c_nationkey, l.o_orderkey, l.o_custkey, l.o_orderdate>
    std::shared_ptr<PhysicalHashJoin> orders_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);

    std::vector<int> build_ids4 = {0};
    std::vector<int> prode_ids4 = {7};
    // <l_orderkey, l_suppkey, l_extendedprice, l_discount, o_orderkey, o_custkey, o_orderdate, c_custkey, c_nationkey, n_nationkey, n_name, n_regionkey, r_regionkey, r_name>
    std::shared_ptr<PhysicalHashJoin> lineitem_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);

    std::vector<int> build_ids5 = {2, 6, 11};
    std::vector<int> prode_ids5 = {1, 1, 0};
    // <r_regionkey, r_name, l.n_nationkey, l.n_name, l.n_regionkey, l.c_custkey, l.c_nationkey, l.o_orderkey, l.o_custkey, l.o_orderdate, l.l_orderkey, l.l_suppkey, l.l_extendedprice, l.l_discount>
    std::shared_ptr<PhysicalHashJoin> last_join_supplier = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids5, prode_ids5);

    //  ================================================构建Filter-3================================================
    //  =======================================表达1=======================================
    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_820425600(820425600); // 1996-01-01
    std::shared_ptr<BoundConstantExpression> right_o_orderdate = std::make_shared<BoundConstantExpression>(value_820425600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_o_orderdate->SetLeft(left_o_orderdate);
    comparisonExpression_o_orderdate->SetRight(right_o_orderdate);
    //  =======================================表达2=======================================
    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_852048000(852048000); // 1997-01-01
    std::shared_ptr<BoundConstantExpression> right_o_orderdate2 = std::make_shared<BoundConstantExpression>(value_852048000);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_o_orderdate2->SetLeft(left_o_orderdate2);
    comparisonExpression_o_orderdate2->SetRight(right_o_orderdate2);
    //  =======================================And表达=======================================
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_o_orderdate, comparisonExpression_o_orderdate2);
    std::shared_ptr<PhysicalFilter> filter_orders = std::make_shared<PhysicalFilter>(conjunctionExpression);

    //  ================================================构建Project-1================================================
    std::shared_ptr<BoundColumnRefExpression> p1_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 14, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 15, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_l_extendedprice, p1_l_discount, p1_n_name};
    // <l_extendedprice, l_discount, n_name>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);

    //  ================================================构建Project-2================================================
    std::shared_ptr<BoundColumnRefExpression> n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);

    Value value_1f(1.0f); // 1997-01-01
    std::shared_ptr<BoundConstantExpression> left_l_discount = std::make_shared<BoundConstantExpression>(value_1f);
    std::shared_ptr<BoundColumnRefExpression> right_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    scalar_function_p sub_function = GetSubFunction();
    std::vector<LogicalType> arguments_type1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    ScalarProjectFunction bound_sub_function("-", arguments_type1, LogicalType::FLOAT, sub_function, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions1 = {left_l_discount, right_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_sub_function, expressions1, nullptr);
    discount_1->alias = "1.00 - l_discount";

    std::shared_ptr<BoundColumnRefExpression> l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 0, 0);
    std::vector<LogicalType> arguments_type = { LogicalType::INTEGER, LogicalType::FLOAT };
    scalar_function_p mul_function = GetMulFunction();
    ScalarProjectFunction bound_mul_function("*", arguments_type, LogicalType::FLOAT, mul_function, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions2 = {l_extendedprice, discount_1};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_mul_function, expressions2, nullptr);
    extendedprice_discount_col->alias = "l_extendedprice * (1.00 - l_discount)";
    std::vector<std::shared_ptr<Expression>> expressions3 = {n_name, extendedprice_discount_col};

    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(expressions3);

    //  ================================================构建HashAgg================================================

    std::vector<int> group_set = {0};
    std::vector<int32_t> agg_set = {1};
    std::vector<int> star_bitmap = {0};
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::SUM };
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {1};
    std::vector<LogicalType> key_types = {LogicalType::DOUBLE};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project2);
    project2->AddChild(project1);
    project1->AddChild(last_join_supplier);
    last_join_supplier->AddChild(lineitem_join_last);
    last_join_supplier->AddChild(scan_supplier);
    lineitem_join_last->AddChild(scan_lineitem);
    lineitem_join_last->AddChild(orders_join_last);
    orders_join_last->AddChild(filter_orders);
    orders_join_last->AddChild(filter_custkey);
    filter_orders->AddChild(scan_orders);
    filter_custkey->AddChild(customer_join_last);
    customer_join_last->AddChild(scan_customer);
    customer_join_last->AddChild(nation_join_region);
    nation_join_region->AddChild(scan_nation);
    nation_join_region->AddChild(filter_region);
    filter_region->AddChild(scan_region);
    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q5执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q6=============================
// 注意修改数据文件路径
TEST(TPCHTest, Q6SingleThreadTest) {
    ////// step-1：构造表数据，分别往分区1和分区20插入数据
    std::vector<std::string> filed_name = {"l_orderkey", "l_partkey", "l_suppkey", "l_linenumber", "l_quantity", "l_extendedprice", "l_discount", "l_tax", "l_returnflag", "l_linestatus", "l_shipdate", "l_commitdate", "l_receiptdate", "l_shipinstruct", "l_shipmode", "l_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::INTEGER;
    LogicalType filed3  = LogicalType::INTEGER;
    LogicalType filed4  = LogicalType::INTEGER;
    LogicalType filed5  = LogicalType::FLOAT;
    LogicalType filed6  = LogicalType::FLOAT;
    LogicalType filed7  = LogicalType::FLOAT;
    LogicalType filed8  = LogicalType::FLOAT;
    LogicalType filed9  = LogicalType::STRING;
    LogicalType filed10 = LogicalType::STRING;
    LogicalType filed11 = LogicalType::INTEGER;
    LogicalType filed12 = LogicalType::INTEGER;
    LogicalType filed13 = LogicalType::INTEGER;
    LogicalType filed14 = LogicalType::STRING;
    LogicalType filed15 = LogicalType::STRING;
    LogicalType filed16 = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    filed_types.push_back(filed6);
    filed_types.push_back(filed7);
    filed_types.push_back(filed8);
    filed_types.push_back(filed9);
    filed_types.push_back(filed10);
    filed_types.push_back(filed11);
    filed_types.push_back(filed12);
    filed_types.push_back(filed13);
    filed_types.push_back(filed14);
    filed_types.push_back(filed15);
    filed_types.push_back(filed16);
    std::string table_name = "lineitem";
    TableInfo table_info(table_name, filed_name, filed_types);
    RC rc = global_catalog.register_table(table_info);
    std::shared_ptr<Table> table;
    rc = global_catalog.get_table(table_name, table);
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    Util::print_socket_free_memory();
    auto start = std::chrono::steady_clock::now();
    std::string fileName = "/home/cwl/data/experiment_1/lineitem.tbl";
    scheduler->submit_task(ImportDataFromLineitem, 1, true, std::ref(table), 1, std::ref(fileName));
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
    auto end = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] 导入数据时间: {}", __FILE__, __LINE__, Util::time_difference(start, end));
    spdlog::info("[{} : {}] Import Data Finish !!!", __FILE__, __LINE__);
    Util::print_socket_free_memory();
    //  ================================================构建Scan================================================
    std::shared_ptr<PhysicalTableScan> scan = std::make_shared<PhysicalTableScan>(table);

    //  ================================================构建Filter================================================
    // 构建Filter表达式
    std::shared_ptr<BoundColumnRefExpression> left_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 10, 0);
    Value value_1996(820425600);
    std::shared_ptr<BoundConstantExpression> right_shipdate = std::make_shared<BoundConstantExpression>(value_1996);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_shipdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_shipdate->SetLeft(left_shipdate);
    comparisonExpression_shipdate->SetRight(right_shipdate);

    std::shared_ptr<BoundColumnRefExpression> left_shipdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 10, 0);
    Value value_1997(852048000);
    std::shared_ptr<BoundConstantExpression> right_shipdate2 = std::make_shared<BoundConstantExpression>(value_1997);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_shipdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_shipdate2->SetLeft(left_shipdate2);
    comparisonExpression_shipdate2->SetRight(right_shipdate2);

    std::shared_ptr<BoundColumnRefExpression> left_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 6, 0);
    Value value_003(0.03f);
    std::shared_ptr<BoundConstantExpression> right_discount = std::make_shared<BoundConstantExpression>(value_003);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_discount = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_discount->SetLeft(left_discount);
    comparisonExpression_discount->SetRight(right_discount);

    std::shared_ptr<BoundColumnRefExpression> left_discount2 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 6, 0);
    Value value_005(0.05f);
    std::shared_ptr<BoundConstantExpression> right_discount2 = std::make_shared<BoundConstantExpression>(value_005);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_discount2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_discount2->SetLeft(left_discount2);
    comparisonExpression_discount2->SetRight(right_discount2);

    std::shared_ptr<BoundColumnRefExpression> left_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 4, 0);
    Value value_24f(24.0f);
    std::shared_ptr<BoundConstantExpression> right_quantity = std::make_shared<BoundConstantExpression>(value_24f);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_quantity = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_quantity->SetLeft(left_quantity);
    comparisonExpression_quantity->SetRight(right_quantity);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression4 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_discount2, comparisonExpression_quantity);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_discount, conjunctionExpression4);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_shipdate2, conjunctionExpression3);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression1 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_shipdate, conjunctionExpression2);

    std::shared_ptr<PhysicalFilter> filter = std::make_shared<PhysicalFilter>(conjunctionExpression1);

    //  ================================================构建Project================================================
    // left_discount
    std::shared_ptr<BoundColumnRefExpression> extendedprice_col = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 5, 0);
    std::vector<LogicalType> arguments_type = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function = GetMulFunction();
    ScalarProjectFunction bound_function("*", arguments_type, LogicalType::FLOAT, function, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions = {extendedprice_col, left_discount};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function, expressions, nullptr);
    extendedprice_discount_col->alias = "l_extendedprice*l_discount";
    std::vector<std::shared_ptr<Expression>> expressions2 = {extendedprice_discount_col};
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(expressions2);

    // TODO: 构建HashAgg
    //  ================================================构建HashAgg================================================
    //const std::vector<AggFunctionType> &aggregate_function_types_,
    //                    const std::vector<int32_t> &group_item_idxs_
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::SUM };
    std::vector<int32_t> group_item_idxs = { 0 };
    std::shared_ptr<PhysicalHashAgg> hashAgg = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, group_item_idxs);
    hashAgg->AddChild(project);
    project->AddChild(filter);
    filter->AddChild(scan);
    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    hashAgg->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q6执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, rc);
}

// 测试2线程Q6查询
// 注意修改数据文件路径
TEST(TPCHTest, Q6TwoThreadTest) {
    ////// step-1：构造表数据，分别往分区1和分区20插入数据
    std::vector<std::string> filed_name = {"l_orderkey", "l_partkey", "l_suppkey", "l_linenumber", "l_quantity", "l_extendedprice", "l_discount", "l_tax", "l_returnflag", "l_linestatus", "l_shipdate", "l_commitdate", "l_receiptdate", "l_shipinstruct", "l_shipmode", "l_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::INTEGER;
    LogicalType filed3  = LogicalType::INTEGER;
    LogicalType filed4  = LogicalType::INTEGER;
    LogicalType filed5  = LogicalType::FLOAT;
    LogicalType filed6  = LogicalType::FLOAT;
    LogicalType filed7  = LogicalType::FLOAT;
    LogicalType filed8  = LogicalType::FLOAT;
    LogicalType filed9  = LogicalType::STRING;
    LogicalType filed10 = LogicalType::STRING;
    LogicalType filed11 = LogicalType::INTEGER;
    LogicalType filed12 = LogicalType::INTEGER;
    LogicalType filed13 = LogicalType::INTEGER;
    LogicalType filed14 = LogicalType::STRING;
    LogicalType filed15 = LogicalType::STRING;
    LogicalType filed16 = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    filed_types.push_back(filed6);
    filed_types.push_back(filed7);
    filed_types.push_back(filed8);
    filed_types.push_back(filed9);
    filed_types.push_back(filed10);
    filed_types.push_back(filed11);
    filed_types.push_back(filed12);
    filed_types.push_back(filed13);
    filed_types.push_back(filed14);
    filed_types.push_back(filed15);
    filed_types.push_back(filed16);
    std::string table_name = "lineitem";
    TableInfo table_info(table_name, filed_name, filed_types);
    RC rc = global_catalog.register_table(table_info);
    std::shared_ptr<Table> table;
    rc = global_catalog.get_table(table_name, table);
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    Util::print_socket_free_memory();
    auto start = std::chrono::steady_clock::now();
    std::string fileName = "/home/cwl/workspace/data/tpch_data/lineitem.tbl_0";
    scheduler->submit_task(ImportDataFromLineitem, 1, true, std::ref(table), 1, std::ref(fileName));
    std::string fileName2 = "/home/cwl/workspace/data/tpch_data/lineitem.tbl_1";
    scheduler->submit_task(ImportDataFromLineitem, 20, true, std::ref(table), 20, std::ref(fileName2));
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
    auto end = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] 导入数据时间: {}", __FILE__, __LINE__, Util::time_difference(start, end));
    spdlog::info("[{} : {}] Import Data Finish !!!", __FILE__, __LINE__);
    Util::print_socket_free_memory();
    //  ================================================构建Scan================================================
    std::shared_ptr<PhysicalTableScan> scan = std::make_shared<PhysicalTableScan>(table);

    //  ================================================构建Filter================================================
    // 构建Filter表达式
    std::shared_ptr<BoundColumnRefExpression> left_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 10, 0);
    Value value_1996(820425600);
    std::shared_ptr<BoundConstantExpression> right_shipdate = std::make_shared<BoundConstantExpression>(value_1996);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_shipdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_shipdate->SetLeft(left_shipdate);
    comparisonExpression_shipdate->SetRight(right_shipdate);

    std::shared_ptr<BoundColumnRefExpression> left_shipdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 10, 0);
    Value value_1997(852048000);
    std::shared_ptr<BoundConstantExpression> right_shipdate2 = std::make_shared<BoundConstantExpression>(value_1997);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_shipdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_shipdate2->SetLeft(left_shipdate2);
    comparisonExpression_shipdate2->SetRight(right_shipdate2);

    std::shared_ptr<BoundColumnRefExpression> left_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 6, 0);
    Value value_003(0.03f);
    std::shared_ptr<BoundConstantExpression> right_discount = std::make_shared<BoundConstantExpression>(value_003);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_discount = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_discount->SetLeft(left_discount);
    comparisonExpression_discount->SetRight(right_discount);

    std::shared_ptr<BoundColumnRefExpression> left_discount2 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 6, 0);
    Value value_005(0.05f);
    std::shared_ptr<BoundConstantExpression> right_discount2 = std::make_shared<BoundConstantExpression>(value_005);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_discount2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_discount2->SetLeft(left_discount2);
    comparisonExpression_discount2->SetRight(right_discount2);

    std::shared_ptr<BoundColumnRefExpression> left_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 4, 0);
    Value value_24f(24.0f);
    std::shared_ptr<BoundConstantExpression> right_quantity = std::make_shared<BoundConstantExpression>(value_24f);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_quantity = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_quantity->SetLeft(left_quantity);
    comparisonExpression_quantity->SetRight(right_quantity);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression4 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_discount2, comparisonExpression_quantity);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_discount, conjunctionExpression4);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_shipdate2, conjunctionExpression3);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression1 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_shipdate, conjunctionExpression2);

    std::shared_ptr<PhysicalFilter> filter = std::make_shared<PhysicalFilter>(conjunctionExpression1);

    //  ================================================构建Project================================================
    // left_discount
    std::shared_ptr<BoundColumnRefExpression> extendedprice_col = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 5, 0);
    std::vector<LogicalType> arguments_type = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function = GetMulFunction();
    ScalarProjectFunction bound_function("*", arguments_type, LogicalType::FLOAT, function, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions = {extendedprice_col, left_discount};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function, expressions, nullptr);
    extendedprice_discount_col->alias = "l_extendedprice*l_discount";
    std::vector<std::shared_ptr<Expression>> expressions2 = {extendedprice_discount_col};
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(expressions2);

    // TODO: 构建HashAgg
    //  ================================================构建HashAgg================================================
    //const std::vector<AggFunctionType> &aggregate_function_types_,
    //                    const std::vector<int32_t> &group_item_idxs_
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::SUM };
    std::vector<int32_t> group_item_idxs = { 0 };
    std::shared_ptr<PhysicalHashAgg> hashAgg = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, group_item_idxs);
    hashAgg->AddChild(project);
    project->AddChild(filter);
    filter->AddChild(scan);
    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    hashAgg->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q6执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));
    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, rc);
}

// 测试4线程Q6查询
// 注意修改数据文件路径
TEST(TPCHTest, Q6FourThreadTest) {
    ////// step-1：构造表数据，分别往分区1和分区20插入数据
    std::vector<std::string> filed_name = {"l_orderkey", "l_partkey", "l_suppkey", "l_linenumber", "l_quantity", "l_extendedprice", "l_discount", "l_tax", "l_returnflag", "l_linestatus", "l_shipdate", "l_commitdate", "l_receiptdate", "l_shipinstruct", "l_shipmode", "l_comment"};
    std::vector<LogicalType> filed_types;
    LogicalType filed1  = LogicalType::INTEGER;
    LogicalType filed2  = LogicalType::INTEGER;
    LogicalType filed3  = LogicalType::INTEGER;
    LogicalType filed4  = LogicalType::INTEGER;
    LogicalType filed5  = LogicalType::FLOAT;
    LogicalType filed6  = LogicalType::FLOAT;
    LogicalType filed7  = LogicalType::FLOAT;
    LogicalType filed8  = LogicalType::FLOAT;
    LogicalType filed9  = LogicalType::STRING;
    LogicalType filed10 = LogicalType::STRING;
    LogicalType filed11 = LogicalType::INTEGER;
    LogicalType filed12 = LogicalType::INTEGER;
    LogicalType filed13 = LogicalType::INTEGER;
    LogicalType filed14 = LogicalType::STRING;
    LogicalType filed15 = LogicalType::STRING;
    LogicalType filed16 = LogicalType::STRING;
    filed_types.push_back(filed1);
    filed_types.push_back(filed2);
    filed_types.push_back(filed3);
    filed_types.push_back(filed4);
    filed_types.push_back(filed5);
    filed_types.push_back(filed6);
    filed_types.push_back(filed7);
    filed_types.push_back(filed8);
    filed_types.push_back(filed9);
    filed_types.push_back(filed10);
    filed_types.push_back(filed11);
    filed_types.push_back(filed12);
    filed_types.push_back(filed13);
    filed_types.push_back(filed14);
    filed_types.push_back(filed15);
    filed_types.push_back(filed16);
    std::string table_name = "lineitem";
    TableInfo table_info(table_name, filed_name, filed_types);
    RC rc = global_catalog.register_table(table_info);
    std::shared_ptr<Table> table;
    rc = global_catalog.get_table(table_name, table);
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    Util::print_socket_free_memory();
    auto start = std::chrono::steady_clock::now();
    std::string fileDir = "/home/cwl/data/experiment_1/4thread";
    std::string fileName1 = fileDir + "/" + "lineitem.tbl_0";
    scheduler->submit_task(ImportDataFromLineitem, 1, true, std::ref(table), 1, std::ref(fileName1));
    std::string fileName2 = fileDir + "/" + "lineitem.tbl_1";
    scheduler->submit_task(ImportDataFromLineitem, 2, true, std::ref(table), 2, std::ref(fileName2));
    std::string fileName3 = fileDir + "/" + "lineitem.tbl_2";
    scheduler->submit_task(ImportDataFromLineitem, 20, true, std::ref(table), 20, std::ref(fileName3));
    std::string fileName4 = fileDir + "/" + "lineitem.tbl_3";
    scheduler->submit_task(ImportDataFromLineitem, 21, true, std::ref(table), 21, std::ref(fileName4));
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return importFinish; });
    auto end = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] 导入数据时间: {}", __FILE__, __LINE__, Util::time_difference(start, end));
    spdlog::info("[{} : {}] Import Data Finish !!!", __FILE__, __LINE__);
    Util::print_socket_free_memory();
    //  ================================================构建Scan================================================
    std::shared_ptr<PhysicalTableScan> scan = std::make_shared<PhysicalTableScan>(table);

    //  ================================================构建Filter================================================
    // 构建Filter表达式
    std::shared_ptr<BoundColumnRefExpression> left_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 10, 0);
    Value value_1996(820425600);
    std::shared_ptr<BoundConstantExpression> right_shipdate = std::make_shared<BoundConstantExpression>(value_1996);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_shipdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_shipdate->SetLeft(left_shipdate);
    comparisonExpression_shipdate->SetRight(right_shipdate);

    std::shared_ptr<BoundColumnRefExpression> left_shipdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 10, 0);
    Value value_1997(852048000);
    std::shared_ptr<BoundConstantExpression> right_shipdate2 = std::make_shared<BoundConstantExpression>(value_1997);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_shipdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_shipdate2->SetLeft(left_shipdate2);
    comparisonExpression_shipdate2->SetRight(right_shipdate2);

    std::shared_ptr<BoundColumnRefExpression> left_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 6, 0);
    Value value_003(0.03f);
    std::shared_ptr<BoundConstantExpression> right_discount = std::make_shared<BoundConstantExpression>(value_003);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_discount = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_discount->SetLeft(left_discount);
    comparisonExpression_discount->SetRight(right_discount);

    std::shared_ptr<BoundColumnRefExpression> left_discount2 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 6, 0);
    Value value_005(0.05f);
    std::shared_ptr<BoundConstantExpression> right_discount2 = std::make_shared<BoundConstantExpression>(value_005);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_discount2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_discount2->SetLeft(left_discount2);
    comparisonExpression_discount2->SetRight(right_discount2);

    std::shared_ptr<BoundColumnRefExpression> left_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 4, 0);
    Value value_24f(24.0f);
    std::shared_ptr<BoundConstantExpression> right_quantity = std::make_shared<BoundConstantExpression>(value_24f);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_quantity = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_quantity->SetLeft(left_quantity);
    comparisonExpression_quantity->SetRight(right_quantity);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression4 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_discount2, comparisonExpression_quantity);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_discount, conjunctionExpression4);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_shipdate2, conjunctionExpression3);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression1 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_shipdate, conjunctionExpression2);

    std::shared_ptr<PhysicalFilter> filter = std::make_shared<PhysicalFilter>(conjunctionExpression1);

    //  ================================================构建Project================================================
    // left_discount
    std::shared_ptr<BoundColumnRefExpression> extendedprice_col = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 5, 0);
    std::vector<LogicalType> arguments_type = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function = GetMulFunction();
    ScalarProjectFunction bound_function("*", arguments_type, LogicalType::FLOAT, function, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions = {extendedprice_col, left_discount};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function, expressions, nullptr);
    extendedprice_discount_col->alias = "l_extendedprice*l_discount";
    std::vector<std::shared_ptr<Expression>> expressions2 = {extendedprice_discount_col};
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(expressions2);

    // TODO: 构建HashAgg
    //  ================================================构建HashAgg================================================
    //const std::vector<AggFunctionType> &aggregate_function_types_,
    //                    const std::vector<int32_t> &group_item_idxs_
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::SUM };
    std::vector<int32_t> group_item_idxs = { 0 };
    std::shared_ptr<PhysicalHashAgg> hashAgg = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, group_item_idxs);
    hashAgg->AddChild(project);
    project->AddChild(filter);
    filter->AddChild(scan);
    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    hashAgg->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q6执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));
    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, rc);
}

// =============================Q7=============================
// 测试单线程Q7查询
TEST(TPCHTest, Q7SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    InsertSupplier(table_supplier, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    InsertOrders(table_orders, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    InsertCustomer(table_customer, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    InsertNation(table_nation, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> supplier_ids = {0, 3};
    // <s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    std::vector<int> nation_ids = {0, 1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation2 = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> customer_ids = {0, 3};
    // <c_custkey, c_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> orders_ids = {0, 1};
    // <o_orderkey, o_custkey>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    std::vector<int> lineitem_ids = {0, 2, 5, 6, 10};
    // <l_orderkey, l_suppkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {1};
    std::vector<int> prode_ids1 = {0};
    // <n_nationkey, n_name, s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalHashJoin> supplier_join_nation = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);

    std::vector<int> build_ids2 = {1};
    std::vector<int> prode_ids2 = {0};
    // <n_nationkey, n_name, c_custkey, c_nationkey>
    std::shared_ptr<PhysicalHashJoin> customer_join_nation = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);

    //  ================================================构建Filter-customer================================================
    std::shared_ptr<BoundColumnRefExpression> left_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_14999(14999);
    std::shared_ptr<BoundConstantExpression> right_c_custkey = std::make_shared<BoundConstantExpression>(value_14999);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_c_custkey = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_c_custkey->SetLeft(left_c_custkey);
    comparisonExpression_c_custkey->SetRight(right_c_custkey);
    // <n_nationkey, n_name, c_custkey, c_nationkey>
    std::shared_ptr<PhysicalFilter> filter_customer = std::make_shared<PhysicalFilter>(comparisonExpression_c_custkey);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids3 = {1};
    std::vector<int> prode_ids3 = {2};
    // <n_nationkey, n_name, c_custkey, c_nationkey, o_orderkey, o_custkey>
    std::shared_ptr<PhysicalHashJoin> orders_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);

    std::vector<int> build_ids4 = {0};
    std::vector<int> prode_ids4 = {4};
    // <n_nationkey, n_name, c_custkey, c_nationkey, o_orderkey, o_custkey, l_orderkey, l_suppkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalHashJoin> lineitem_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);

    //  ================================================构建Filter-lineitem================================================
    std::shared_ptr<BoundColumnRefExpression> left_l_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 4, 0);
    Value value_788889600(788889600);
    std::shared_ptr<BoundConstantExpression> right_l_shipdate = std::make_shared<BoundConstantExpression>(value_788889600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_l_shipdate->SetLeft(left_l_shipdate);
    comparisonExpression_l_shipdate->SetRight(right_l_shipdate);

    std::shared_ptr<BoundColumnRefExpression> left_l_shipdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 4, 0);
    Value value_851961600(851961600);
    std::shared_ptr<BoundConstantExpression> right_l_shipdate2 = std::make_shared<BoundConstantExpression>(value_851961600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_l_shipdate2->SetLeft(left_l_shipdate2);
    comparisonExpression_l_shipdate2->SetRight(right_l_shipdate2);

    std::shared_ptr<BoundConjunctionExpression> l_shipdate_and = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_l_shipdate, comparisonExpression_l_shipdate2);

    // <l_orderkey, l_suppkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalFilter> filter_lineitem = std::make_shared<PhysicalFilter>(l_shipdate_and);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids5 = {7};
    std::vector<int> prode_ids5 = {2};
    // <n_nationkey, n_name, s_suppkey, s_nationkey, n_nationkey, n_name, c_custkey, c_nationkey, o_orderkey, o_custkey, l_orderkey, l_suppkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalHashJoin> last_join_supplier_join_nation = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids5, prode_ids5);

    //  ================================================构建Filter-join================================================
    std::shared_ptr<BoundColumnRefExpression> left_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_FRANCE("FRANCE");
    std::shared_ptr<BoundConstantExpression> right_n_name = std::make_shared<BoundConstantExpression>(value_FRANCE);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_n_name = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_n_name->SetLeft(left_n_name);
    comparisonExpression_n_name->SetRight(right_n_name);

    std::shared_ptr<BoundColumnRefExpression> left_n_name2 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    Value value_GERMANY("GERMANY");
    std::shared_ptr<BoundConstantExpression> right_n_name2 = std::make_shared<BoundConstantExpression>(value_GERMANY);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_n_name2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_n_name2->SetLeft(left_n_name2);
    comparisonExpression_n_name2->SetRight(right_n_name2);

    std::shared_ptr<BoundConjunctionExpression> n_name_and = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_n_name, comparisonExpression_n_name2);

    std::shared_ptr<BoundColumnRefExpression> left_n_name3 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundConstantExpression> right_n_name3 = std::make_shared<BoundConstantExpression>(value_GERMANY);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_n_name3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_n_name3->SetLeft(left_n_name3);
    comparisonExpression_n_name3->SetRight(right_n_name3);

    std::shared_ptr<BoundColumnRefExpression> left_n_name4 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    std::shared_ptr<BoundConstantExpression> right_n_name4 = std::make_shared<BoundConstantExpression>(value_FRANCE);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_n_name4 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_n_name4->SetLeft(left_n_name4);
    comparisonExpression_n_name4->SetRight(right_n_name4);

    std::shared_ptr<BoundConjunctionExpression> n_name_and2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_n_name3, comparisonExpression_n_name4);

    std::shared_ptr<BoundConjunctionExpression> n_name_or = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_OR, n_name_and, n_name_and2);

    // <n_nationkey, n_name, s_suppkey, s_nationkey, n_nationkey, n_name, c_custkey, c_nationkey, o_orderkey, o_custkey, l_orderkey, l_suppkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalFilter> filter_join = std::make_shared<PhysicalFilter>(n_name_or);

    // ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p_n1_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p_n2_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> p_l_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 14, 0);
    std::shared_ptr<BoundColumnRefExpression> p_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 12, 0);
    std::shared_ptr<BoundColumnRefExpression> p_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 13, 0);

    std::vector<LogicalType> arguments1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function1 = GetSubFunction();
    ScalarProjectFunction bound_function1("-", arguments1, LogicalType::FLOAT, function1, nullptr);
    Value value_1(1.0f);
    std::shared_ptr<BoundConstantExpression> constant1_col = std::make_shared<BoundConstantExpression>(value_1);
    std::vector<std::shared_ptr<Expression>> expressions1 = {constant1_col, p_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function1, expressions1, nullptr);
    discount_1_col->alias = "1-l_discount";

    std::vector<LogicalType> arguments2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function2 = GetMulFunction();
    ScalarProjectFunction bound_function2("*", arguments2, LogicalType::FLOAT, function2, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions2 = {p_l_extendedprice, discount_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function2, expressions2, nullptr);
    extendedprice_discount_1_col->alias = "l_extendedprice*(1-l_discount)";

    std::vector<LogicalType> arguments3 = { LogicalType::INTEGER, LogicalType::INTEGER };
    scalar_function_p function3 = GetExtractYearFunction();
    ScalarProjectFunction bound_function3("extract_year", arguments3, LogicalType::INTEGER, function3, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions3 = {p_l_shipdate, p_l_shipdate};
    std::shared_ptr<BoundProjectFunctionExpression> extract_year = std::make_shared<BoundProjectFunctionExpression>(LogicalType::INTEGER, bound_function3, expressions3, nullptr);
    extract_year->alias = "l_year";

    std::vector<std::shared_ptr<Expression>> p_expressions = {p_n1_name, p_n2_name, extract_year, extendedprice_discount_1_col};
    // <n_name, n_name, l_year, l_extendedprice * (1 - l_discount)>
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(p_expressions);

    // 构建HashAgg
    std::vector<int> group_set = {0, 1, 2};
    std::vector<int> agg_set = {3};
    std::vector<int> star_bitmap = {0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM};
    // <n_name, n_name, l_year, Sum(l_extendedprice * (1 - l_discount))>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0, 1, 2};
    std::vector<LogicalType> key_types = {LogicalType::STRING, LogicalType::STRING, LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING, SortOrder::ASCENDING, SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project);
    project->AddChild(filter_join);
    filter_join->AddChild(last_join_supplier_join_nation);
    last_join_supplier_join_nation->AddChild(lineitem_join_last);
    last_join_supplier_join_nation->AddChild(supplier_join_nation);
    supplier_join_nation->AddChild(scan_supplier);
    supplier_join_nation->AddChild(scan_nation);
    lineitem_join_last->AddChild(filter_lineitem);
    lineitem_join_last->AddChild(orders_join_last);
    filter_lineitem->AddChild(scan_lineitem);
    orders_join_last->AddChild(scan_orders);
    orders_join_last->AddChild(filter_customer);
    filter_customer->AddChild(customer_join_nation);
    customer_join_nation->AddChild(scan_customer);
    customer_join_nation->AddChild(scan_nation2);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q7执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q7查询
TEST(TPCHTest, Q7FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    std::vector<std::string> supplier_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "supplier.tbl_" + std::to_string(i);
        supplier_file_names.emplace_back(file_name);
    }
    InsertSupplierMul(table_supplier, scheduler, work_ids, partition_idxs, supplier_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    std::vector<std::string> customer_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "customer.tbl_" + std::to_string(i);
        customer_file_names.emplace_back(file_name);
    }
    InsertCustomerMul(table_customer, scheduler, work_ids, partition_idxs, customer_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    std::vector<std::string> nation_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "nation.tbl_" + std::to_string(i);
        nation_file_names.emplace_back(file_name);
    }
    InsertNationMul(table_nation, scheduler, work_ids, partition_idxs, nation_file_names);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> supplier_ids = {0, 3};
    // <s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    std::vector<int> nation_ids = {0, 1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation2 = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> customer_ids = {0, 3};
    // <c_custkey, c_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> orders_ids = {0, 1};
    // <o_orderkey, o_custkey>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    std::vector<int> lineitem_ids = {0, 2, 5, 6, 10};
    // <l_orderkey, l_suppkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {1};
    std::vector<int> prode_ids1 = {0};
    // <n_nationkey, n_name, s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalHashJoin> supplier_join_nation = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);

    std::vector<int> build_ids2 = {1};
    std::vector<int> prode_ids2 = {0};
    // <n_nationkey, n_name, c_custkey, c_nationkey>
    std::shared_ptr<PhysicalHashJoin> customer_join_nation = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);

    //  ================================================构建Filter-customer================================================
    std::shared_ptr<BoundColumnRefExpression> left_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_14999(14999);
    std::shared_ptr<BoundConstantExpression> right_c_custkey = std::make_shared<BoundConstantExpression>(value_14999);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_c_custkey = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_c_custkey->SetLeft(left_c_custkey);
    comparisonExpression_c_custkey->SetRight(right_c_custkey);
    // <n_nationkey, n_name, c_custkey, c_nationkey>
    std::shared_ptr<PhysicalFilter> filter_customer = std::make_shared<PhysicalFilter>(comparisonExpression_c_custkey);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids3 = {1};
    std::vector<int> prode_ids3 = {2};
    // <n_nationkey, n_name, c_custkey, c_nationkey, o_orderkey, o_custkey>
    std::shared_ptr<PhysicalHashJoin> orders_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);

    std::vector<int> build_ids4 = {0};
    std::vector<int> prode_ids4 = {4};
    // <n_nationkey, n_name, c_custkey, c_nationkey, o_orderkey, o_custkey, l_orderkey, l_suppkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalHashJoin> lineitem_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);

    //  ================================================构建Filter-lineitem================================================
    std::shared_ptr<BoundColumnRefExpression> left_l_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 4, 0);
    Value value_788889600(788889600);
    std::shared_ptr<BoundConstantExpression> right_l_shipdate = std::make_shared<BoundConstantExpression>(value_788889600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_l_shipdate->SetLeft(left_l_shipdate);
    comparisonExpression_l_shipdate->SetRight(right_l_shipdate);

    std::shared_ptr<BoundColumnRefExpression> left_l_shipdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 4, 0);
    Value value_851961600(851961600);
    std::shared_ptr<BoundConstantExpression> right_l_shipdate2 = std::make_shared<BoundConstantExpression>(value_851961600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_l_shipdate2->SetLeft(left_l_shipdate2);
    comparisonExpression_l_shipdate2->SetRight(right_l_shipdate2);

    std::shared_ptr<BoundConjunctionExpression> l_shipdate_and = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_l_shipdate, comparisonExpression_l_shipdate2);

    // <l_orderkey, l_suppkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalFilter> filter_lineitem = std::make_shared<PhysicalFilter>(l_shipdate_and);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids5 = {7};
    std::vector<int> prode_ids5 = {2};
    // <n_nationkey, n_name, s_suppkey, s_nationkey, n_nationkey, n_name, c_custkey, c_nationkey, o_orderkey, o_custkey, l_orderkey, l_suppkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalHashJoin> last_join_supplier_join_nation = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids5, prode_ids5);

    //  ================================================构建Filter-join================================================
    std::shared_ptr<BoundColumnRefExpression> left_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_FRANCE("FRANCE");
    std::shared_ptr<BoundConstantExpression> right_n_name = std::make_shared<BoundConstantExpression>(value_FRANCE);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_n_name = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_n_name->SetLeft(left_n_name);
    comparisonExpression_n_name->SetRight(right_n_name);

    std::shared_ptr<BoundColumnRefExpression> left_n_name2 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    Value value_GERMANY("GERMANY");
    std::shared_ptr<BoundConstantExpression> right_n_name2 = std::make_shared<BoundConstantExpression>(value_GERMANY);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_n_name2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_n_name2->SetLeft(left_n_name2);
    comparisonExpression_n_name2->SetRight(right_n_name2);

    std::shared_ptr<BoundConjunctionExpression> n_name_and = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_n_name, comparisonExpression_n_name2);

    std::shared_ptr<BoundColumnRefExpression> left_n_name3 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundConstantExpression> right_n_name3 = std::make_shared<BoundConstantExpression>(value_GERMANY);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_n_name3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_n_name3->SetLeft(left_n_name3);
    comparisonExpression_n_name3->SetRight(right_n_name3);

    std::shared_ptr<BoundColumnRefExpression> left_n_name4 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    std::shared_ptr<BoundConstantExpression> right_n_name4 = std::make_shared<BoundConstantExpression>(value_FRANCE);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_n_name4 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_n_name4->SetLeft(left_n_name4);
    comparisonExpression_n_name4->SetRight(right_n_name4);

    std::shared_ptr<BoundConjunctionExpression> n_name_and2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_n_name3, comparisonExpression_n_name4);

    std::shared_ptr<BoundConjunctionExpression> n_name_or = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_OR, n_name_and, n_name_and2);

    // <n_nationkey, n_name, s_suppkey, s_nationkey, n_nationkey, n_name, c_custkey, c_nationkey, o_orderkey, o_custkey, l_orderkey, l_suppkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalFilter> filter_join = std::make_shared<PhysicalFilter>(n_name_or);

    // ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p_n1_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p_n2_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> p_l_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 14, 0);
    std::shared_ptr<BoundColumnRefExpression> p_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 12, 0);
    std::shared_ptr<BoundColumnRefExpression> p_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 13, 0);

    std::vector<LogicalType> arguments1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function1 = GetSubFunction();
    ScalarProjectFunction bound_function1("-", arguments1, LogicalType::FLOAT, function1, nullptr);
    Value value_1(1.0f);
    std::shared_ptr<BoundConstantExpression> constant1_col = std::make_shared<BoundConstantExpression>(value_1);
    std::vector<std::shared_ptr<Expression>> expressions1 = {constant1_col, p_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function1, expressions1, nullptr);
    discount_1_col->alias = "1-l_discount";

    std::vector<LogicalType> arguments2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function2 = GetMulFunction();
    ScalarProjectFunction bound_function2("*", arguments2, LogicalType::FLOAT, function2, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions2 = {p_l_extendedprice, discount_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function2, expressions2, nullptr);
    extendedprice_discount_1_col->alias = "l_extendedprice*(1-l_discount)";

    std::vector<LogicalType> arguments3 = { LogicalType::INTEGER, LogicalType::INTEGER };
    scalar_function_p function3 = GetExtractYearFunction();
    ScalarProjectFunction bound_function3("extract_year", arguments3, LogicalType::INTEGER, function3, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions3 = {p_l_shipdate, p_l_shipdate};
    std::shared_ptr<BoundProjectFunctionExpression> extract_year = std::make_shared<BoundProjectFunctionExpression>(LogicalType::INTEGER, bound_function3, expressions3, nullptr);
    extract_year->alias = "l_year";

    std::vector<std::shared_ptr<Expression>> p_expressions = {p_n1_name, p_n2_name, extract_year, extendedprice_discount_1_col};
    // <n_name, n_name, l_year, l_extendedprice * (1 - l_discount)>
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(p_expressions);

    // 构建HashAgg
    std::vector<int> group_set = {0, 1, 2};
    std::vector<int> agg_set = {3};
    std::vector<int> star_bitmap = {0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM};
    // <n_name, n_name, l_year, Sum(l_extendedprice * (1 - l_discount))>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0, 1, 2};
    std::vector<LogicalType> key_types = {LogicalType::STRING, LogicalType::STRING, LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING, SortOrder::ASCENDING, SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project);
    project->AddChild(filter_join);
    filter_join->AddChild(last_join_supplier_join_nation);
    last_join_supplier_join_nation->AddChild(lineitem_join_last);
    last_join_supplier_join_nation->AddChild(supplier_join_nation);
    supplier_join_nation->AddChild(scan_supplier);
    supplier_join_nation->AddChild(scan_nation);
    lineitem_join_last->AddChild(filter_lineitem);
    lineitem_join_last->AddChild(orders_join_last);
    filter_lineitem->AddChild(scan_lineitem);
    orders_join_last->AddChild(scan_orders);
    orders_join_last->AddChild(filter_customer);
    filter_customer->AddChild(customer_join_nation);
    customer_join_nation->AddChild(scan_customer);
    customer_join_nation->AddChild(scan_nation2);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q7执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q8=============================
// 测试单线程Q8查询
TEST(TPCHTest, Q8SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    InsertSupplier(table_supplier, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    InsertOrders(table_orders, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    InsertCustomer(table_customer, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    InsertNation(table_nation, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    InsertPart(table_part, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Region表数据
    std::shared_ptr<Table> table_region;
    InsertRegion(table_region, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertRegion Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> part_ids = {0, 4};
    // <p_partkey, p_type>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    std::vector<int> lineitem_ids = {0, 1, 2, 5, 6};
    // <l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> orders_ids = {0, 1, 4};
    // <o_orderkey, o_custkey, o_orderdate>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    std::vector<int> customer_ids = {0, 3};
    // <c_custkey, c_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> supplier_ids = {0, 3};
    // <s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    std::vector<int> nation_ids1 = {0, 1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation1 = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids1);

    std::vector<int> nation_ids2 = {0, 2};
    // <n_nationkey, n_regionkey>
    std::shared_ptr<PhysicalTableScan> scan_nation2 = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids2);

    std::vector<int> region_ids = {0, 1};
    // <r_regionkey, r_name>
    std::shared_ptr<PhysicalTableScan> scan_region = std::make_shared<PhysicalTableScan>(table_region, -1, region_ids);

    //  ================================================构建Filter-part================================================
    std::shared_ptr<BoundColumnRefExpression> left_p_type = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_ECONOMY("ECONOMY ANODIZED STEEL");
    std::shared_ptr<BoundConstantExpression> right_p_type = std::make_shared<BoundConstantExpression>(value_ECONOMY);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_p_type = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_p_type->SetLeft(left_p_type);
    comparisonExpression_p_type->SetRight(right_p_type);
    // <p_partkey, p_type>
    std::shared_ptr<PhysicalFilter> filter_part = std::make_shared<PhysicalFilter>(comparisonExpression_p_type);
    filter_part->exp_name = "filter-part";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {1};
    // <l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount, p_partkey, p_type>
    std::shared_ptr<PhysicalHashJoin> part_join_lineitem = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    part_join_lineitem->exp_name = "7";
    //  ================================================构建Filter-orders================================================
    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_788889600(788889600);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate = std::make_shared<BoundConstantExpression>(value_788889600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_o_orderdate->SetLeft(left_o_orderdate);
    comparisonExpression_o_orderdate->SetRight(right_o_orderdate);

    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_851961600(851961600);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate2 = std::make_shared<BoundConstantExpression>(value_851961600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_o_orderdate2->SetLeft(left_o_orderdate2);
    comparisonExpression_o_orderdate2->SetRight(right_o_orderdate2);

    std::shared_ptr<BoundConjunctionExpression> o_orderdate_and = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_o_orderdate, comparisonExpression_o_orderdate2);
    // <c_custkey, c_nationkey>
    std::shared_ptr<PhysicalFilter> filter_orders = std::make_shared<PhysicalFilter>(o_orderdate_and);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {0};
    // <o_orderkey, o_custkey, o_orderdate, l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount, p_partkey, p_type>
    std::shared_ptr<PhysicalHashJoin> last_join_orders = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    last_join_orders->exp_name = "6";

    //  ================================================构建Filter-customer================================================
    std::shared_ptr<BoundColumnRefExpression> left_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    Value value_14999(14999);
    std::shared_ptr<BoundConstantExpression> right_c_custkey = std::make_shared<BoundConstantExpression>(value_14999);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_c_custkey = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_c_custkey->SetLeft(left_c_custkey);
    comparisonExpression_c_custkey->SetRight(right_c_custkey);
    // <c_custkey, c_nationkey>
    std::shared_ptr<PhysicalFilter> filter_customer = std::make_shared<PhysicalFilter>(comparisonExpression_c_custkey);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids3 = {1};
    std::vector<int> prode_ids3 = {0};
    // <c_custkey, c_nationkey, o_orderkey, o_custkey, o_orderdate, l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount, p_partkey, p_type>
    std::shared_ptr<PhysicalHashJoin> last_join_customer = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    last_join_customer->exp_name = "5";
    //  ================================================构建Filter-region================================================
    std::shared_ptr<BoundColumnRefExpression> left_r_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_AMERICA("AMERICA");
    std::shared_ptr<BoundConstantExpression> right_r_name = std::make_shared<BoundConstantExpression>(value_AMERICA);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_r_name = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_r_name->SetLeft(left_r_name);
    comparisonExpression_r_name->SetRight(right_r_name);
    // <r_regionkey, r_name>
    std::shared_ptr<PhysicalFilter> filter_region = std::make_shared<PhysicalFilter>(comparisonExpression_r_name);

    std::vector<int> build_ids4 = {1};
    std::vector<int> prode_ids4 = {0};
    // <r_regionkey, r_name, n_nationkey, n_regionkey>
    std::shared_ptr<PhysicalHashJoin> nation2_join_region = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);
    nation2_join_region->exp_name = "4";

    std::vector<int> build_ids5 = {2};
    std::vector<int> prode_ids5 = {1};
    // <c_custkey, c_nationkey, o_orderkey, o_custkey, o_orderdate, l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount, p_partkey, p_type, r_regionkey, r_name, n_nationkey, n_regionkey>
    std::shared_ptr<PhysicalHashJoin> nationkey_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids5, prode_ids5);
    nationkey_join_last->exp_name = "3";

    std::vector<int> build_ids6 = {7};
    std::vector<int> prode_ids6 = {0};
    // <s_suppkey, s_nationkey, c_custkey, c_nationkey, o_orderkey, o_custkey, o_orderdate, l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount, p_partkey, p_type, r_regionkey, r_name, n_nationkey, n_regionkey>
    std::shared_ptr<PhysicalHashJoin> supplier_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids6, prode_ids6);
    supplier_join_last->exp_name = "2";

    std::vector<int> build_ids7 = {0};
    std::vector<int> prode_ids7 = {1};
    // <s_suppkey, s_nationkey, c_custkey, c_nationkey, o_orderkey, o_custkey, o_orderdate, l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount, p_partkey, p_type, r_regionkey, r_name, n_nationkey, n_regionkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> nation1_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids7, prode_ids7);
    nation1_join_last->exp_name = "1";
    // ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 10, 0);
    std::shared_ptr<BoundColumnRefExpression> p_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 11, 0);
    std::shared_ptr<BoundColumnRefExpression> p_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 19, 0);

    std::vector<LogicalType> arguments1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function1 = GetSubFunction();
    ScalarProjectFunction bound_function1("-", arguments1, LogicalType::FLOAT, function1, nullptr);
    Value value_1(1.0f);
    std::shared_ptr<BoundConstantExpression> constant1_col = std::make_shared<BoundConstantExpression>(value_1);
    std::vector<std::shared_ptr<Expression>> expressions1 = {constant1_col, p_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function1, expressions1, nullptr);
    discount_1_col->alias = "1-l_discount";

    std::vector<LogicalType> arguments2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function2 = GetMulFunction();
    ScalarProjectFunction bound_function2("*", arguments2, LogicalType::FLOAT, function2, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions2 = {p_l_extendedprice, discount_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function2, expressions2, nullptr);
    extendedprice_discount_1_col->alias = "volume";

    std::vector<LogicalType> arguments3 = { LogicalType::INTEGER, LogicalType::INTEGER };
    scalar_function_p function3 = GetExtractYearFunction();
    ScalarProjectFunction bound_function3("extract_year", arguments3, LogicalType::INTEGER, function3, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions3 = {p_o_orderdate, p_o_orderdate};
    std::shared_ptr<BoundProjectFunctionExpression> extract_year = std::make_shared<BoundProjectFunctionExpression>(LogicalType::INTEGER, bound_function3, expressions3, nullptr);
    extract_year->alias = "o_year";

    std::vector<std::shared_ptr<Expression>> p_expressions = {extract_year, extendedprice_discount_1_col, p_n_name};
    // <o_year, volume, n_name(nation)>
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(p_expressions);

    // case-when Project
    std::shared_ptr<BoundColumnRefExpression> nation_col = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> volume_col = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value value_p("BRAZIL");
    std::shared_ptr<BoundConstantExpression> constant_col = std::make_shared<BoundConstantExpression>(value_p);

    Value value_t(0.0F);
    std::shared_ptr<BoundConstantExpression> constant0_col = std::make_shared<BoundConstantExpression>(value_t);
    std::shared_ptr<BoundComparisonExpression> when_expr = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    when_expr->SetLeft(nation_col);
    when_expr->SetRight(constant_col);

    std::shared_ptr<BoundCaseExpression> case_expr = std::make_shared<BoundCaseExpression>();
    case_expr->SetWhenExpr(when_expr);
    case_expr->SetThenExpr(volume_col);
    case_expr->SetElseExpr(constant0_col);
    case_expr->alias = "CASE_NATION";

    std::shared_ptr<BoundColumnRefExpression> p2_o_year = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);

    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_o_year, case_expr, volume_col};
    // <o_year, case_nation, volume>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);

    // 构建HashAgg
    std::vector<int> group_set = {0};
    std::vector<int> agg_set = {1, 2};
    std::vector<int> star_bitmap = {0, 0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM, AggFunctionType::SUM};
    // <o_year, Sum(case_nation), Sum(volume)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    // ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p3_o_year = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_sum_case_nation = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_sum_volume = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 2, 0);

    std::vector<LogicalType> arguments4 = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p function4 = GetDivFunction();
    ScalarProjectFunction bound_function4("/", arguments4, LogicalType::DOUBLE, function4, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions = {p3_sum_case_nation, p3_sum_volume};
    std::shared_ptr<BoundProjectFunctionExpression> p3_case_nation_div_volume = std::make_shared<BoundProjectFunctionExpression>(LogicalType::DOUBLE, bound_function4, p3_expressions, nullptr);
    p3_case_nation_div_volume->alias = "mkt_share";

    std::vector<std::shared_ptr<Expression>> p3_expressions2 = {p3_o_year, p3_case_nation_div_volume};
    // <o_year, mkt_share>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions2);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(project3);
    project3->AddChild(hashAgg);
    hashAgg->AddChild(project2);
    project2->AddChild(project);
    project->AddChild(nation1_join_last);
    nation1_join_last->AddChild(scan_nation1);
    nation1_join_last->AddChild(supplier_join_last);
    supplier_join_last->AddChild(nationkey_join_last);
    supplier_join_last->AddChild(scan_supplier);
    nationkey_join_last->AddChild(nation2_join_region);
    nationkey_join_last->AddChild(last_join_customer);
    nation2_join_region->AddChild(scan_nation2);
    nation2_join_region->AddChild(filter_region);
    filter_region->AddChild(scan_region);
    last_join_customer->AddChild(last_join_orders);
    last_join_customer->AddChild(filter_customer);
    filter_customer->AddChild(scan_customer);
    last_join_orders->AddChild(part_join_lineitem);
    last_join_orders->AddChild(filter_orders);
    filter_orders->AddChild(scan_orders);
    part_join_lineitem->AddChild(filter_part);
    part_join_lineitem->AddChild(scan_lineitem);
    filter_part->AddChild(scan_part);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q8执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q8查询
TEST(TPCHTest, Q8FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    std::vector<std::string> supplier_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "supplier.tbl_" + std::to_string(i);
        supplier_file_names.emplace_back(file_name);
    }
    InsertSupplierMul(table_supplier, scheduler, work_ids, partition_idxs, supplier_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    std::vector<std::string> customer_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "customer.tbl_" + std::to_string(i);
        customer_file_names.emplace_back(file_name);
    }
    InsertCustomerMul(table_customer, scheduler, work_ids, partition_idxs, customer_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    std::vector<std::string> nation_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "nation.tbl_" + std::to_string(i);
        nation_file_names.emplace_back(file_name);
    }
    InsertNationMul(table_nation, scheduler, work_ids, partition_idxs, nation_file_names);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    std::vector<std::string> part_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "part.tbl_" + std::to_string(i);
        part_file_names.emplace_back(file_name);
    };
    InsertPartMul(table_part, scheduler, work_ids, partition_idxs, part_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Region表数据
    std::shared_ptr<Table> table_region;
    std::vector<std::string> region_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "region.tbl_" + std::to_string(i);
        region_file_names.emplace_back(file_name);
    };
    InsertRegionMul(table_region, scheduler, work_ids, partition_idxs, region_file_names);
    importFinish = false;
    spdlog::info("[{} : {}] InsertRegion Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> part_ids = {0, 4};
    // <p_partkey, p_type>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    std::vector<int> lineitem_ids = {0, 1, 2, 5, 6};
    // <l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> orders_ids = {0, 1, 4};
    // <o_orderkey, o_custkey, o_orderdate>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    std::vector<int> customer_ids = {0, 3};
    // <c_custkey, c_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> supplier_ids = {0, 3};
    // <s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    std::vector<int> nation_ids1 = {0, 1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation1 = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids1);

    std::vector<int> nation_ids2 = {0, 2};
    // <n_nationkey, n_regionkey>
    std::shared_ptr<PhysicalTableScan> scan_nation2 = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids2);

    std::vector<int> region_ids = {0, 1};
    // <r_regionkey, r_name>
    std::shared_ptr<PhysicalTableScan> scan_region = std::make_shared<PhysicalTableScan>(table_region, -1, region_ids);

    //  ================================================构建Filter-part================================================
    std::shared_ptr<BoundColumnRefExpression> left_p_type = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_ECONOMY("ECONOMY ANODIZED STEEL");
    std::shared_ptr<BoundConstantExpression> right_p_type = std::make_shared<BoundConstantExpression>(value_ECONOMY);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_p_type = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_p_type->SetLeft(left_p_type);
    comparisonExpression_p_type->SetRight(right_p_type);
    // <p_partkey, p_type>
    std::shared_ptr<PhysicalFilter> filter_part = std::make_shared<PhysicalFilter>(comparisonExpression_p_type);
    filter_part->exp_name = "filter-part";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {1};
    // <l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount, p_partkey, p_type>
    std::shared_ptr<PhysicalHashJoin> part_join_lineitem = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    part_join_lineitem->exp_name = "7";
    //  ================================================构建Filter-orders================================================
    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_788889600(788889600);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate = std::make_shared<BoundConstantExpression>(value_788889600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_o_orderdate->SetLeft(left_o_orderdate);
    comparisonExpression_o_orderdate->SetRight(right_o_orderdate);

    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_851961600(851961600);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate2 = std::make_shared<BoundConstantExpression>(value_851961600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_o_orderdate2->SetLeft(left_o_orderdate2);
    comparisonExpression_o_orderdate2->SetRight(right_o_orderdate2);

    std::shared_ptr<BoundConjunctionExpression> o_orderdate_and = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_o_orderdate, comparisonExpression_o_orderdate2);
    // <c_custkey, c_nationkey>
    std::shared_ptr<PhysicalFilter> filter_orders = std::make_shared<PhysicalFilter>(o_orderdate_and);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {0};
    // <o_orderkey, o_custkey, o_orderdate, l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount, p_partkey, p_type>
    std::shared_ptr<PhysicalHashJoin> last_join_orders = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    last_join_orders->exp_name = "6";

    //  ================================================构建Filter-customer================================================
    std::shared_ptr<BoundColumnRefExpression> left_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    Value value_14999(14999);
    std::shared_ptr<BoundConstantExpression> right_c_custkey = std::make_shared<BoundConstantExpression>(value_14999);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_c_custkey = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_c_custkey->SetLeft(left_c_custkey);
    comparisonExpression_c_custkey->SetRight(right_c_custkey);
    // <c_custkey, c_nationkey>
    std::shared_ptr<PhysicalFilter> filter_customer = std::make_shared<PhysicalFilter>(comparisonExpression_c_custkey);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids3 = {1};
    std::vector<int> prode_ids3 = {0};
    // <c_custkey, c_nationkey, o_orderkey, o_custkey, o_orderdate, l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount, p_partkey, p_type>
    std::shared_ptr<PhysicalHashJoin> last_join_customer = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    last_join_customer->exp_name = "5";
    //  ================================================构建Filter-region================================================
    std::shared_ptr<BoundColumnRefExpression> left_r_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_AMERICA("AMERICA");
    std::shared_ptr<BoundConstantExpression> right_r_name = std::make_shared<BoundConstantExpression>(value_AMERICA);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_r_name = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_r_name->SetLeft(left_r_name);
    comparisonExpression_r_name->SetRight(right_r_name);
    // <r_regionkey, r_name>
    std::shared_ptr<PhysicalFilter> filter_region = std::make_shared<PhysicalFilter>(comparisonExpression_r_name);

    std::vector<int> build_ids4 = {1};
    std::vector<int> prode_ids4 = {0};
    // <r_regionkey, r_name, n_nationkey, n_regionkey>
    std::shared_ptr<PhysicalHashJoin> nation2_join_region = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);
    nation2_join_region->exp_name = "4";

    std::vector<int> build_ids5 = {2};
    std::vector<int> prode_ids5 = {1};
    // <c_custkey, c_nationkey, o_orderkey, o_custkey, o_orderdate, l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount, p_partkey, p_type, r_regionkey, r_name, n_nationkey, n_regionkey>
    std::shared_ptr<PhysicalHashJoin> nationkey_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids5, prode_ids5);
    nationkey_join_last->exp_name = "3";

    std::vector<int> build_ids6 = {7};
    std::vector<int> prode_ids6 = {0};
    // <s_suppkey, s_nationkey, c_custkey, c_nationkey, o_orderkey, o_custkey, o_orderdate, l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount, p_partkey, p_type, r_regionkey, r_name, n_nationkey, n_regionkey>
    std::shared_ptr<PhysicalHashJoin> supplier_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids6, prode_ids6);
    supplier_join_last->exp_name = "2";

    std::vector<int> build_ids7 = {0};
    std::vector<int> prode_ids7 = {1};
    // <s_suppkey, s_nationkey, c_custkey, c_nationkey, o_orderkey, o_custkey, o_orderdate, l_orderkey, l_partkey, l_suppkey, l_extendedprice, l_discount, p_partkey, p_type, r_regionkey, r_name, n_nationkey, n_regionkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> nation1_join_last = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids7, prode_ids7);
    nation1_join_last->exp_name = "1";
    // ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 10, 0);
    std::shared_ptr<BoundColumnRefExpression> p_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 11, 0);
    std::shared_ptr<BoundColumnRefExpression> p_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 19, 0);

    std::vector<LogicalType> arguments1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function1 = GetSubFunction();
    ScalarProjectFunction bound_function1("-", arguments1, LogicalType::FLOAT, function1, nullptr);
    Value value_1(1.0f);
    std::shared_ptr<BoundConstantExpression> constant1_col = std::make_shared<BoundConstantExpression>(value_1);
    std::vector<std::shared_ptr<Expression>> expressions1 = {constant1_col, p_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function1, expressions1, nullptr);
    discount_1_col->alias = "1-l_discount";

    std::vector<LogicalType> arguments2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function2 = GetMulFunction();
    ScalarProjectFunction bound_function2("*", arguments2, LogicalType::FLOAT, function2, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions2 = {p_l_extendedprice, discount_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function2, expressions2, nullptr);
    extendedprice_discount_1_col->alias = "volume";

    std::vector<LogicalType> arguments3 = { LogicalType::INTEGER, LogicalType::INTEGER };
    scalar_function_p function3 = GetExtractYearFunction();
    ScalarProjectFunction bound_function3("extract_year", arguments3, LogicalType::INTEGER, function3, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions3 = {p_o_orderdate, p_o_orderdate};
    std::shared_ptr<BoundProjectFunctionExpression> extract_year = std::make_shared<BoundProjectFunctionExpression>(LogicalType::INTEGER, bound_function3, expressions3, nullptr);
    extract_year->alias = "o_year";

    std::vector<std::shared_ptr<Expression>> p_expressions = {extract_year, extendedprice_discount_1_col, p_n_name};
    // <o_year, volume, n_name(nation)>
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(p_expressions);

    // case-when Project
    std::shared_ptr<BoundColumnRefExpression> nation_col = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> volume_col = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value value_p("BRAZIL");
    std::shared_ptr<BoundConstantExpression> constant_col = std::make_shared<BoundConstantExpression>(value_p);

    Value value_t(0.0F);
    std::shared_ptr<BoundConstantExpression> constant0_col = std::make_shared<BoundConstantExpression>(value_t);
    std::shared_ptr<BoundComparisonExpression> when_expr = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    when_expr->SetLeft(nation_col);
    when_expr->SetRight(constant_col);

    std::shared_ptr<BoundCaseExpression> case_expr = std::make_shared<BoundCaseExpression>();
    case_expr->SetWhenExpr(when_expr);
    case_expr->SetThenExpr(volume_col);
    case_expr->SetElseExpr(constant0_col);
    case_expr->alias = "CASE_NATION";

    std::shared_ptr<BoundColumnRefExpression> p2_o_year = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);

    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_o_year, case_expr, volume_col};
    // <o_year, case_nation, volume>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);

    // 构建HashAgg
    std::vector<int> group_set = {0};
    std::vector<int> agg_set = {1, 2};
    std::vector<int> star_bitmap = {0, 0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM, AggFunctionType::SUM};
    // <o_year, Sum(case_nation), Sum(volume)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    // ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p3_o_year = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_sum_case_nation = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_sum_volume = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 2, 0);

    std::vector<LogicalType> arguments4 = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p function4 = GetDivFunction();
    ScalarProjectFunction bound_function4("/", arguments4, LogicalType::DOUBLE, function4, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions = {p3_sum_case_nation, p3_sum_volume};
    std::shared_ptr<BoundProjectFunctionExpression> p3_case_nation_div_volume = std::make_shared<BoundProjectFunctionExpression>(LogicalType::DOUBLE, bound_function4, p3_expressions, nullptr);
    p3_case_nation_div_volume->alias = "mkt_share";

    std::vector<std::shared_ptr<Expression>> p3_expressions2 = {p3_o_year, p3_case_nation_div_volume};
    // <o_year, mkt_share>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions2);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(project3);
    project3->AddChild(hashAgg);
    hashAgg->AddChild(project2);
    project2->AddChild(project);
    project->AddChild(nation1_join_last);
    nation1_join_last->AddChild(scan_nation1);
    nation1_join_last->AddChild(supplier_join_last);
    supplier_join_last->AddChild(nationkey_join_last);
    supplier_join_last->AddChild(scan_supplier);
    nationkey_join_last->AddChild(nation2_join_region);
    nationkey_join_last->AddChild(last_join_customer);
    nation2_join_region->AddChild(scan_nation2);
    nation2_join_region->AddChild(filter_region);
    filter_region->AddChild(scan_region);
    last_join_customer->AddChild(last_join_orders);
    last_join_customer->AddChild(filter_customer);
    filter_customer->AddChild(scan_customer);
    last_join_orders->AddChild(part_join_lineitem);
    last_join_orders->AddChild(filter_orders);
    filter_orders->AddChild(scan_orders);
    part_join_lineitem->AddChild(filter_part);
    part_join_lineitem->AddChild(scan_lineitem);
    filter_part->AddChild(scan_part);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q8执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q9=============================
// 测试单线程Q9查询
TEST(TPCHTest, Q9SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    InsertSupplier(table_supplier, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    InsertNation(table_nation, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    InsertPart(table_part, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Partsupp表数据
    std::shared_ptr<Table> table_partsupp;
    InsertPartsupp(table_partsupp, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPartsupp Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    InsertOrders(table_orders, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> nation_ids = {0, 1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> supplier_ids = {0, 3};
    // <s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    std::vector<int> part_ids = {0, 1};
    // <p_partkey, p_name>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    std::vector<int> partsupp_ids = {0, 1, 3};
    // <ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalTableScan> scan_partsupp = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);

    std::vector<int> lineitem_ids = {0, 1, 2, 4, 5, 6};
    // <l_orderkey, l_partkey, l_suppkey, l_quantity, l_extendedprice, l_discount>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> orders_ids = {0, 4};
    // <o_orderkey, o_orderdate>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids5 = {0};
    std::vector<int> prode_ids5 = {1};
    // <s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join_5 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids5, prode_ids5);
    join_5->exp_name = "5";

    std::vector<int> build_ids4 = {0};
    std::vector<int> prode_ids4 = {0};
    // <ps_partkey, ps_suppkey, ps_supplycost, p_partkey>
    std::shared_ptr<PhysicalHashJoin> join_4 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);
    join_4->exp_name = "4";

    std::shared_ptr<BoundColumnRefExpression> p4_p_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::vector<std::shared_ptr<Expression>> p4_expressions = {p4_p_partkey};
    // <p_partkey>
    std::shared_ptr<PhysicalProject> project4 = std::make_shared<PhysicalProject>(p4_expressions);

    std::string like_pattern = "%green%";
    ScalarFunction bound_function = LikeFun::GetLikeFunction();
    std::shared_ptr<BoundColumnRefExpression> left_p_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value(like_pattern);
    std::shared_ptr<BoundConstantExpression> right_p_name = std::make_shared<BoundConstantExpression>(value);
    std::vector<std::shared_ptr<Expression>> arguments;
    arguments.push_back(std::move(left_p_name));
    arguments.push_back(std::move(right_p_name));
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments, nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);
    // <p_partkey, p_name>
    std::shared_ptr<PhysicalFilter> filter_part = std::make_shared<PhysicalFilter>(functionExpression);
    filter_part->exp_name = "filter-part";

    std::vector<int> build_ids3 = {0};
    std::vector<int> prode_ids3 = {1};
    // <ps_partkey, ps_suppkey, ps_supplycost, p_partkey, s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join_3 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    join_3->exp_name = "3";

    std::vector<int> build_ids2 = {0, 1, 3, 4};
    std::vector<int> prode_ids2 = {1, 2, 1, 2};
    // <l_orderkey, l_partkey, l_suppkey, l_quantity, l_extendedprice, l_discount, ps_partkey, ps_suppkey, ps_supplycost, p_partkey, s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join_2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join_2->exp_name = "2";

    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {0};
    // <o_orderkey, o_orderdate, l_orderkey, l_partkey, l_suppkey, l_quantity, l_extendedprice, l_discount, ps_partkey, ps_suppkey, ps_supplycost, p_partkey, s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join_1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join_1->exp_name = "1";

    // ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p3_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 15, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 7, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 10, 0);

    std::vector<LogicalType> p3_arguments1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p p3_function1 = GetSubFunction();
    ScalarProjectFunction p3_bound_function1("-", p3_arguments1, LogicalType::FLOAT, p3_function1, nullptr);
    Value value_1(1.0f);
    std::shared_ptr<BoundConstantExpression> constant1_col = std::make_shared<BoundConstantExpression>(value_1);
    std::vector<std::shared_ptr<Expression>> p3_expressions1 = {constant1_col, p3_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p3_bound_function1, p3_expressions1, nullptr);
    discount_1_col->alias = "1-l_discount";

    std::vector<LogicalType> p3_arguments2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p p3_function2 = GetMulFunction();
    ScalarProjectFunction p3_bound_function2("*", p3_arguments2, LogicalType::FLOAT, p3_function2, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions2 = {p3_l_extendedprice, discount_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p3_bound_function2, p3_expressions2, nullptr);
    extendedprice_discount_1_col->alias = "l_extendedprice * (1 - l_discount)";

    std::vector<LogicalType> p3_arguments3 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p p3_function3 = GetMulFunction();
    ScalarProjectFunction p3_bound_function3("*", p3_arguments3, LogicalType::FLOAT, p3_function3, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions3 = {p3_ps_supplycost, p3_l_quantity};
    std::shared_ptr<BoundProjectFunctionExpression> ps_supplycost_l_quantity = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p3_bound_function3, p3_expressions3, nullptr);
    ps_supplycost_l_quantity->alias = "ps_supplycost * l_quantity";

    std::vector<LogicalType> p3_arguments4 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p p3_function4 = GetSubFunction();
    ScalarProjectFunction p3_bound_function4("-", p3_arguments4, LogicalType::FLOAT, p3_function4, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions4 = {extendedprice_discount_1_col, ps_supplycost_l_quantity};
    std::shared_ptr<BoundProjectFunctionExpression> amount = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p3_bound_function4, p3_expressions4, nullptr);
    amount->alias = "amount";

    std::vector<LogicalType> p3_arguments5 = { LogicalType::INTEGER, LogicalType::INTEGER };
    scalar_function_p p3_function5 = GetExtractYearFunction();
    ScalarProjectFunction p3_bound_function5("extract_year", p3_arguments5, LogicalType::INTEGER, p3_function5, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions5 = {p3_o_orderdate, p3_o_orderdate};
    std::shared_ptr<BoundProjectFunctionExpression> o_year = std::make_shared<BoundProjectFunctionExpression>(LogicalType::INTEGER, p3_bound_function5, p3_expressions5, nullptr);
    discount_1_col->alias = "o_year";

    std::vector<std::shared_ptr<Expression>> p3_expressions6 = {p3_n_name, o_year, amount};
    // <n_name(nation), o_year, amount>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions6);

    // 构建HashAgg
    std::vector<int> group_set = {0, 1};
    std::vector<int> agg_set = {2};
    std::vector<int> star_bitmap = {0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM};
    // <nation, o_year, Sum(amount)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0, 1};
    std::vector<LogicalType> key_types = {LogicalType::STRING, LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING, SortOrder::DESCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project3);
    project3->AddChild(join_1);
    join_1->AddChild(join_2);
    join_1->AddChild(scan_orders);
    join_2->AddChild(join_3);
    join_2->AddChild(scan_lineitem);
    join_3->AddChild(join_5);
    join_3->AddChild(join_4);
    join_5->AddChild(scan_nation);
    join_5->AddChild(scan_supplier);
    join_4->AddChild(project4);
    join_4->AddChild(scan_partsupp);
    project4->AddChild(filter_part);
    filter_part->AddChild(scan_part);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q9执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q9查询
TEST(TPCHTest, Q9FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    std::vector<std::string> supplier_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "supplier.tbl_" + std::to_string(i);
        supplier_file_names.emplace_back(file_name);
    }
    InsertSupplierMul(table_supplier, scheduler, work_ids, partition_idxs, supplier_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    std::vector<std::string> nation_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "nation.tbl_" + std::to_string(i);
        nation_file_names.emplace_back(file_name);
    }
    InsertNationMul(table_nation, scheduler, work_ids, partition_idxs, nation_file_names);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    std::vector<std::string> part_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "part.tbl_" + std::to_string(i);
        part_file_names.emplace_back(file_name);
    }
    InsertPartMul(table_part, scheduler, work_ids, partition_idxs, part_file_names);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Partsupp表数据
    std::shared_ptr<Table> table_partsupp;
    std::vector<std::string> partsupp_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "partsupp.tbl_" + std::to_string(i);
        partsupp_file_names.emplace_back(file_name);
    }
    InsertPartsuppMul(table_partsupp, scheduler, work_ids, partition_idxs, partsupp_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertPartsupp Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> nation_ids = {0, 1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> supplier_ids = {0, 3};
    // <s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    std::vector<int> part_ids = {0, 1};
    // <p_partkey, p_name>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    std::vector<int> partsupp_ids = {0, 1, 3};
    // <ps_partkey, ps_suppkey, ps_supplycost>
    std::shared_ptr<PhysicalTableScan> scan_partsupp = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);

    std::vector<int> lineitem_ids = {0, 1, 2, 4, 5, 6};
    // <l_orderkey, l_partkey, l_suppkey, l_quantity, l_extendedprice, l_discount>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> orders_ids = {0, 4};
    // <o_orderkey, o_orderdate>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids5 = {0};
    std::vector<int> prode_ids5 = {1};
    // <s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join_5 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids5, prode_ids5);
    join_5->exp_name = "5";

    std::vector<int> build_ids4 = {0};
    std::vector<int> prode_ids4 = {0};
    // <ps_partkey, ps_suppkey, ps_supplycost, p_partkey>
    std::shared_ptr<PhysicalHashJoin> join_4 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);
    join_4->exp_name = "4";

    std::shared_ptr<BoundColumnRefExpression> p4_p_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::vector<std::shared_ptr<Expression>> p4_expressions = {p4_p_partkey};
    // <p_partkey>
    std::shared_ptr<PhysicalProject> project4 = std::make_shared<PhysicalProject>(p4_expressions);

    std::string like_pattern = "%green%";
    ScalarFunction bound_function = LikeFun::GetLikeFunction();
    std::shared_ptr<BoundColumnRefExpression> left_p_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value(like_pattern);
    std::shared_ptr<BoundConstantExpression> right_p_name = std::make_shared<BoundConstantExpression>(value);
    std::vector<std::shared_ptr<Expression>> arguments;
    arguments.push_back(std::move(left_p_name));
    arguments.push_back(std::move(right_p_name));
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments, nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);
    // <p_partkey, p_name>
    std::shared_ptr<PhysicalFilter> filter_part = std::make_shared<PhysicalFilter>(functionExpression);
    filter_part->exp_name = "filter-part";

    std::vector<int> build_ids3 = {0};
    std::vector<int> prode_ids3 = {1};
    // <ps_partkey, ps_suppkey, ps_supplycost, p_partkey, s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join_3 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    join_3->exp_name = "3";

    std::vector<int> build_ids2 = {0, 1, 3, 4};
    std::vector<int> prode_ids2 = {1, 2, 1, 2};
    // <l_orderkey, l_partkey, l_suppkey, l_quantity, l_extendedprice, l_discount, ps_partkey, ps_suppkey, ps_supplycost, p_partkey, s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join_2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join_2->exp_name = "2";

    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {0};
    // <o_orderkey, o_orderdate, l_orderkey, l_partkey, l_suppkey, l_quantity, l_extendedprice, l_discount, ps_partkey, ps_suppkey, ps_supplycost, p_partkey, s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join_1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join_1->exp_name = "1";

    // ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p3_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 15, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 7, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 10, 0);

    std::vector<LogicalType> p3_arguments1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p p3_function1 = GetSubFunction();
    ScalarProjectFunction p3_bound_function1("-", p3_arguments1, LogicalType::FLOAT, p3_function1, nullptr);
    Value value_1(1.0f);
    std::shared_ptr<BoundConstantExpression> constant1_col = std::make_shared<BoundConstantExpression>(value_1);
    std::vector<std::shared_ptr<Expression>> p3_expressions1 = {constant1_col, p3_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p3_bound_function1, p3_expressions1, nullptr);
    discount_1_col->alias = "1-l_discount";

    std::vector<LogicalType> p3_arguments2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p p3_function2 = GetMulFunction();
    ScalarProjectFunction p3_bound_function2("*", p3_arguments2, LogicalType::FLOAT, p3_function2, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions2 = {p3_l_extendedprice, discount_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p3_bound_function2, p3_expressions2, nullptr);
    extendedprice_discount_1_col->alias = "l_extendedprice * (1 - l_discount)";

    std::vector<LogicalType> p3_arguments3 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p p3_function3 = GetMulFunction();
    ScalarProjectFunction p3_bound_function3("*", p3_arguments3, LogicalType::FLOAT, p3_function3, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions3 = {p3_ps_supplycost, p3_l_quantity};
    std::shared_ptr<BoundProjectFunctionExpression> ps_supplycost_l_quantity = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p3_bound_function3, p3_expressions3, nullptr);
    ps_supplycost_l_quantity->alias = "ps_supplycost * l_quantity";

    std::vector<LogicalType> p3_arguments4 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p p3_function4 = GetSubFunction();
    ScalarProjectFunction p3_bound_function4("-", p3_arguments4, LogicalType::FLOAT, p3_function4, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions4 = {extendedprice_discount_1_col, ps_supplycost_l_quantity};
    std::shared_ptr<BoundProjectFunctionExpression> amount = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p3_bound_function4, p3_expressions4, nullptr);
    amount->alias = "amount";

    std::vector<LogicalType> p3_arguments5 = { LogicalType::INTEGER, LogicalType::INTEGER };
    scalar_function_p p3_function5 = GetExtractYearFunction();
    ScalarProjectFunction p3_bound_function5("extract_year", p3_arguments5, LogicalType::INTEGER, p3_function5, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions5 = {p3_o_orderdate, p3_o_orderdate};
    std::shared_ptr<BoundProjectFunctionExpression> o_year = std::make_shared<BoundProjectFunctionExpression>(LogicalType::INTEGER, p3_bound_function5, p3_expressions5, nullptr);
    discount_1_col->alias = "o_year";

    std::vector<std::shared_ptr<Expression>> p3_expressions6 = {p3_n_name, o_year, amount};
    // <n_name(nation), o_year, amount>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions6);

    // 构建HashAgg
    std::vector<int> group_set = {0, 1};
    std::vector<int> agg_set = {2};
    std::vector<int> star_bitmap = {0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM};
    // <nation, o_year, Sum(amount)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0, 1};
    std::vector<LogicalType> key_types = {LogicalType::STRING, LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING, SortOrder::DESCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project3);
    project3->AddChild(join_1);
    join_1->AddChild(join_2);
    join_1->AddChild(scan_orders);
    join_2->AddChild(join_3);
    join_2->AddChild(scan_lineitem);
    join_3->AddChild(join_5);
    join_3->AddChild(join_4);
    join_5->AddChild(scan_nation);
    join_5->AddChild(scan_supplier);
    join_4->AddChild(project4);
    join_4->AddChild(scan_partsupp);
    project4->AddChild(filter_part);
    filter_part->AddChild(scan_part);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q9执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q10=============================
// 测试单线程Q10查询
TEST(TPCHTest, Q10SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    InsertNation(table_nation, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    InsertCustomer(table_customer, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    InsertOrders(table_orders, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> nation_ids = {0, 1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> customer_ids = {0, 1, 2, 3, 4, 5, 7};
    // <c_custkey, c_name, c_address, c_nationkey, c_phone, c_acctbal, c_comment>
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> lineitem_ids = {0, 5, 6, 8};
    // <l_orderkey, l_extendedprice, l_discount, l_returnflag>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> orders_ids = {0, 1, 4};
    // <o_orderkey, o_custkey, o_orderdate>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {3};
    // <c_custkey, c_name, c_address, c_nationkey, c_phone, c_acctbal, c_comment, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join_1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join_1->exp_name = "1";

    std::shared_ptr<BoundColumnRefExpression> f1_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    Value value_14999(14999);
    std::shared_ptr<BoundConstantExpression> right_constant = std::make_shared<BoundConstantExpression>(value_14999);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_c_custkey = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_c_custkey->SetLeft(f1_c_custkey);
    comparisonExpression_c_custkey->SetRight(right_constant);
    // <c_custkey, c_name, c_address, c_nationkey, c_phone, c_acctbal, c_comment, n_nationkey, n_name>
    std::shared_ptr<PhysicalFilter> filter_1 = std::make_shared<PhysicalFilter>(comparisonExpression_c_custkey);

    std::shared_ptr<BoundColumnRefExpression> p1_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_c_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_c_address = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_c_phone = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 4, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_c_comment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 8, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_c_custkey, p1_c_name, p1_c_address, p1_c_phone, p1_c_acctbal, p1_c_comment, p1_n_name};
    // <c_custkey, c_name, c_address, c_phone, c_acctbal, c_comment, n_name>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);

    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_749404800(749404800);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate = std::make_shared<BoundConstantExpression>(value_749404800);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_o_orderdate->SetLeft(left_o_orderdate);
    comparisonExpression_o_orderdate->SetRight(right_o_orderdate);

    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_757353600(757353600);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate2 = std::make_shared<BoundConstantExpression>(value_757353600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_o_orderdate2->SetLeft(left_o_orderdate2);
    comparisonExpression_o_orderdate2->SetRight(right_o_orderdate2);
    std::shared_ptr<BoundConjunctionExpression> o_orderdate_and = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_o_orderdate, comparisonExpression_o_orderdate2);

    // <o_orderkey, o_custkey, o_orderdate>
    std::shared_ptr<PhysicalFilter> filter_2 = std::make_shared<PhysicalFilter>(o_orderdate_and);

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {1};
    // <o_orderkey, o_custkey, o_orderdate, c_custkey, c_name, c_address, c_phone, c_acctbal, c_comment, n_name>
    std::shared_ptr<PhysicalHashJoin> join_2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join_2->exp_name = "2";

    std::shared_ptr<BoundColumnRefExpression> f3_l_returnflag = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 3, 0);
    Value value_R("R");
    std::shared_ptr<BoundConstantExpression> right_l_returnflag = std::make_shared<BoundConstantExpression>(value_R);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_returnflag = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_l_returnflag->SetLeft(f3_l_returnflag);
    comparisonExpression_l_returnflag->SetRight(right_l_returnflag);
    // <l_orderkey, l_extendedprice, l_discount, l_returnflag>
    std::shared_ptr<PhysicalFilter> filter_3 = std::make_shared<PhysicalFilter>(comparisonExpression_l_returnflag);

    std::vector<int> build_ids3 = {0};
    std::vector<int> prode_ids3 = {0};
    // <l_orderkey, l_extendedprice, l_discount, l_returnflag, o_orderkey, o_custkey, o_orderdate, c_custkey, c_name, c_address, c_phone, c_acctbal, c_comment, n_name>
    std::shared_ptr<PhysicalHashJoin> join_3 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    join_3->exp_name = "3";

    std::shared_ptr<BoundColumnRefExpression> p2_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 7, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 8, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 11, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 13, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_address = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 9, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_phone = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 10, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_comment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 12, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);

    std::vector<LogicalType> arguments1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function1 = GetSubFunction();
    ScalarProjectFunction bound_function1("-", arguments1, LogicalType::FLOAT, function1, nullptr);
    Value value_1(1.0f);
    std::shared_ptr<BoundConstantExpression> constant1_col = std::make_shared<BoundConstantExpression>(value_1);
    std::vector<std::shared_ptr<Expression>> expressions1 = {constant1_col, p2_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function1, expressions1, nullptr);
    discount_1_col->alias = "1-l_discount";

    std::vector<LogicalType> arguments2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function2 = GetMulFunction();
    ScalarProjectFunction bound_function2("*", arguments2, LogicalType::FLOAT, function2, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions2 = {p2_l_extendedprice, discount_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> revenue = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function2, expressions2, nullptr);
    revenue->alias = "revenue";

    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_c_custkey, p2_c_name, revenue, p2_c_acctbal, p2_n_name, p2_c_address, p2_c_phone, p2_c_comment};
    // <c_custkey, c_name, revenue, c_acctbal, n_name, c_address, c_phone, c_comment>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    // 构建HashAgg
    std::vector<int> group_set = {0, 1, 3, 6, 4, 5, 7};
    std::vector<int> agg_set = {2};
    std::vector<int> star_bitmap = {0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM};
    // <c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment, Sum(revenue)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {7};
    std::vector<LogicalType> key_types = {LogicalType::DOUBLE};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project2);
    project2->AddChild(join_3);
    join_3->AddChild(join_2);
    join_3->AddChild(filter_3);
    filter_3->AddChild(scan_lineitem);
    join_2->AddChild(project1);
    join_2->AddChild(filter_2);
    filter_2->AddChild(scan_orders);
    project1->AddChild(filter_1);
    filter_1->AddChild(join_1);
    join_1->AddChild(scan_nation);
    join_1->AddChild(scan_customer);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q10执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q10查询
TEST(TPCHTest, Q10FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    std::vector<std::string> nation_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "nation.tbl_" + std::to_string(i);
        nation_file_names.emplace_back(file_name);
    }
    InsertNationMul(table_nation, scheduler, work_ids, partition_idxs, nation_file_names);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    std::vector<std::string> customer_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "customer.tbl_" + std::to_string(i);
        customer_file_names.emplace_back(file_name);
    }
    InsertCustomerMul(table_customer, scheduler, work_ids, partition_idxs, customer_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> nation_ids = {0, 1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> customer_ids = {0, 1, 2, 3, 4, 5, 7};
    // <c_custkey, c_name, c_address, c_nationkey, c_phone, c_acctbal, c_comment>
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> lineitem_ids = {0, 5, 6, 8};
    // <l_orderkey, l_extendedprice, l_discount, l_returnflag>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> orders_ids = {0, 1, 4};
    // <o_orderkey, o_custkey, o_orderdate>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {3};
    // <c_custkey, c_name, c_address, c_nationkey, c_phone, c_acctbal, c_comment, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join_1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join_1->exp_name = "1";

    std::shared_ptr<BoundColumnRefExpression> f1_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    Value value_14999(14999);
    std::shared_ptr<BoundConstantExpression> right_constant = std::make_shared<BoundConstantExpression>(value_14999);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_c_custkey = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO);
    comparisonExpression_c_custkey->SetLeft(f1_c_custkey);
    comparisonExpression_c_custkey->SetRight(right_constant);
    // <c_custkey, c_name, c_address, c_nationkey, c_phone, c_acctbal, c_comment, n_nationkey, n_name>
    std::shared_ptr<PhysicalFilter> filter_1 = std::make_shared<PhysicalFilter>(comparisonExpression_c_custkey);

    std::shared_ptr<BoundColumnRefExpression> p1_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_c_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_c_address = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_c_phone = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 4, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_c_comment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 8, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_c_custkey, p1_c_name, p1_c_address, p1_c_phone, p1_c_acctbal, p1_c_comment, p1_n_name};
    // <c_custkey, c_name, c_address, c_phone, c_acctbal, c_comment, n_name>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);

    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_749404800(749404800);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate = std::make_shared<BoundConstantExpression>(value_749404800);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_o_orderdate->SetLeft(left_o_orderdate);
    comparisonExpression_o_orderdate->SetRight(right_o_orderdate);

    std::shared_ptr<BoundColumnRefExpression> left_o_orderdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    Value value_757353600(757353600);
    std::shared_ptr<BoundConstantExpression> right_o_orderdate2 = std::make_shared<BoundConstantExpression>(value_757353600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_o_orderdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_o_orderdate2->SetLeft(left_o_orderdate2);
    comparisonExpression_o_orderdate2->SetRight(right_o_orderdate2);
    std::shared_ptr<BoundConjunctionExpression> o_orderdate_and = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_o_orderdate, comparisonExpression_o_orderdate2);

    // <o_orderkey, o_custkey, o_orderdate>
    std::shared_ptr<PhysicalFilter> filter_2 = std::make_shared<PhysicalFilter>(o_orderdate_and);

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {1};
    // <o_orderkey, o_custkey, o_orderdate, c_custkey, c_name, c_address, c_phone, c_acctbal, c_comment, n_name>
    std::shared_ptr<PhysicalHashJoin> join_2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join_2->exp_name = "2";

    std::shared_ptr<BoundColumnRefExpression> f3_l_returnflag = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 3, 0);
    Value value_R("R");
    std::shared_ptr<BoundConstantExpression> right_l_returnflag = std::make_shared<BoundConstantExpression>(value_R);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_returnflag = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_l_returnflag->SetLeft(f3_l_returnflag);
    comparisonExpression_l_returnflag->SetRight(right_l_returnflag);
    // <l_orderkey, l_extendedprice, l_discount, l_returnflag>
    std::shared_ptr<PhysicalFilter> filter_3 = std::make_shared<PhysicalFilter>(comparisonExpression_l_returnflag);

    std::vector<int> build_ids3 = {0};
    std::vector<int> prode_ids3 = {0};
    // <l_orderkey, l_extendedprice, l_discount, l_returnflag, o_orderkey, o_custkey, o_orderdate, c_custkey, c_name, c_address, c_phone, c_acctbal, c_comment, n_name>
    std::shared_ptr<PhysicalHashJoin> join_3 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    join_3->exp_name = "3";

    std::shared_ptr<BoundColumnRefExpression> p2_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 7, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 8, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 11, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 13, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_address = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 9, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_phone = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 10, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_comment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 12, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);

    std::vector<LogicalType> arguments1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function1 = GetSubFunction();
    ScalarProjectFunction bound_function1("-", arguments1, LogicalType::FLOAT, function1, nullptr);
    Value value_1(1.0f);
    std::shared_ptr<BoundConstantExpression> constant1_col = std::make_shared<BoundConstantExpression>(value_1);
    std::vector<std::shared_ptr<Expression>> expressions1 = {constant1_col, p2_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function1, expressions1, nullptr);
    discount_1_col->alias = "1-l_discount";

    std::vector<LogicalType> arguments2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function2 = GetMulFunction();
    ScalarProjectFunction bound_function2("*", arguments2, LogicalType::FLOAT, function2, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions2 = {p2_l_extendedprice, discount_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> revenue = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function2, expressions2, nullptr);
    revenue->alias = "revenue";

    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_c_custkey, p2_c_name, revenue, p2_c_acctbal, p2_n_name, p2_c_address, p2_c_phone, p2_c_comment};
    // <c_custkey, c_name, revenue, c_acctbal, n_name, c_address, c_phone, c_comment>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    // 构建HashAgg
    std::vector<int> group_set = {0, 1, 3, 6, 4, 5, 7};
    std::vector<int> agg_set = {2};
    std::vector<int> star_bitmap = {0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM};
    // <c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment, Sum(revenue)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {7};
    std::vector<LogicalType> key_types = {LogicalType::DOUBLE};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project2);
    project2->AddChild(join_3);
    join_3->AddChild(join_2);
    join_3->AddChild(filter_3);
    filter_3->AddChild(scan_lineitem);
    join_2->AddChild(project1);
    join_2->AddChild(filter_2);
    filter_2->AddChild(scan_orders);
    project1->AddChild(filter_1);
    filter_1->AddChild(join_1);
    join_1->AddChild(scan_nation);
    join_1->AddChild(scan_customer);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q10执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q11=============================
// 测试单线程Q11查询
TEST(TPCHTest, Q11SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    InsertNation(table_nation, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    InsertSupplier(table_supplier, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    // 插入Partsupp表数据
    std::shared_ptr<Table> table_partsupp;
    InsertPartsupp(table_partsupp, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPartsupp Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> nation_ids = {0, 1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation1 = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);
    std::shared_ptr<PhysicalTableScan> scan_nation2 = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> supplier_ids = {0, 3};
    // <s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier1 = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);
    std::shared_ptr<PhysicalTableScan> scan_supplier2 = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    std::vector<int> partsupp_ids = {1, 2, 3};
    // <ps_suppkey, ps_availqty, ps_supplycost>
    std::shared_ptr<PhysicalTableScan> scan_partsupp1 = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);

    std::vector<int> partsupp_ids2 = {0, 1, 2, 3};
    // <ps_partkey, ps_suppkey, ps_availqty, ps_supplycost>
    std::shared_ptr<PhysicalTableScan> scan_partsupp2 = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids2);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_GERMANY("GERMANY");
    std::shared_ptr<BoundConstantExpression> right_constant = std::make_shared<BoundConstantExpression>(value_GERMANY);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_n_name = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_n_name->SetLeft(f1_n_name);
    comparisonExpression_n_name->SetRight(right_constant);
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(comparisonExpression_n_name);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {1};
    // <s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join1->exp_name = "1";

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {0};
    // <ps_suppkey, ps_availqty, ps_supplycost, s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join2->exp_name = "2";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_ps_availqty = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::vector<LogicalType> p1_arguments = { LogicalType::FLOAT, LogicalType::INTEGER };
    scalar_function_p p1_function = GetMulFunction();
    ScalarProjectFunction p1_bound_function("*", p1_arguments, LogicalType::FLOAT, p1_function, nullptr);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_ps_supplycost, p1_ps_availqty};
    std::shared_ptr<BoundProjectFunctionExpression> p1_alias = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p1_bound_function, p1_expressions, nullptr);
    p1_alias->alias = "ps_supplycost * ps_availqty";

    std::vector<std::shared_ptr<Expression>> p1_expressions2 = {p1_alias};
    // <(ps_supplycost * ps_availqty)>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions2);
    project1->exp_name = "1";

    //  ================================================构建HashAgg================================================
    std::vector<int> agg_set = {0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM};
    // <Sum(ps_supplycost * ps_availqty)>
    std::shared_ptr<PhysicalHashAgg> hashAgg1 = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, agg_set);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p2_sum = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 0, 0);
    Value value_00001(0.0001);
    std::shared_ptr<BoundConstantExpression> p2_constant = std::make_shared<BoundConstantExpression>(value_00001);
    std::vector<LogicalType> p2_arguments = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p p2_function = GetMulFunction();
    ScalarProjectFunction p2_bound_function("*", p2_arguments, LogicalType::DOUBLE, p2_function, nullptr);
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_sum, p2_constant};
    std::shared_ptr<BoundProjectFunctionExpression> p2_alias = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p2_bound_function, p2_expressions, nullptr);
    p2_alias->alias = "Sum(ps_supplycost * ps_availqty) * 0.0001";

    std::vector<std::shared_ptr<Expression>> p2_expressions2 = {p2_alias};
    // <Sum(ps_supplycost * ps_availqty) * 0.0001>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions2);
    project2->exp_name = "2";
    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f2_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundConstantExpression> right_constant2 = std::make_shared<BoundConstantExpression>(value_GERMANY);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_n_name2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_n_name2->SetLeft(f2_n_name);
    comparisonExpression_n_name2->SetRight(right_constant2);
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(comparisonExpression_n_name2);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids3 = {0};
    std::vector<int> prode_ids3 = {1};
    // <s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join3 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    join3->exp_name = "3";

    std::vector<int> build_ids4 = {0};
    std::vector<int> prode_ids4 = {1};
    // <ps_partkey, ps_suppkey, ps_availqty, ps_supplycost, s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join4 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);
    join4->exp_name = "4";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p3_ps_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_ps_availqty = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::vector<LogicalType> p3_arguments = { LogicalType::FLOAT, LogicalType::INTEGER };
    scalar_function_p p3_function = GetMulFunction();
    ScalarProjectFunction p3_bound_function("*", p3_arguments, LogicalType::FLOAT, p3_function, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions = {p3_ps_supplycost, p3_ps_availqty};
    std::shared_ptr<BoundProjectFunctionExpression> p3_alias = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p3_bound_function, p3_expressions, nullptr);
    p3_alias->alias = "ps_supplycost * ps_availqty";

    std::vector<std::shared_ptr<Expression>> p3_expressions2 = {p3_ps_partkey, p3_alias};
    // <ps_partkey, (ps_supplycost * ps_availqty)>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions2);
    project3->exp_name = "3";
    // 构建HashAgg
    std::vector<int> group_set2 = {0};
    std::vector<int> agg_set2 = {1};
    std::vector<int> star_bitmap2 = {0};
    std::vector<AggFunctionType> aggregate_function_types2 = {AggFunctionType::SUM};
    // <ps_partkey, Sum(ps_supplycost * ps_availqty)-value>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg2 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set2, agg_set2, star_bitmap2, aggregate_function_types2);

    //  ================================================构建NestLoopJoin================================================
    std::vector<int> build_ids5 = {0};
    std::vector<int> prode_ids5 = {1};
    std::vector<ExpressionTypes> compare_types = { ExpressionTypes::COMPARE_GREATERTHAN };
    // <ps_partkey, Sum(ps_supplycost * ps_availqty)-value, Sum(ps_supplycost * ps_availqty) * 0.0001>
    std::shared_ptr<PhysicalNestedLoopJoin> join5 = std::make_shared<PhysicalNestedLoopJoin>(JoinTypes::INNER, build_ids5, prode_ids5, compare_types);
    join5->exp_name = "5";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p4_ps_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p4_value = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p4_expressions = {p4_ps_partkey, p4_value};
    // <ps_partkey, value>
    std::shared_ptr<PhysicalProject> project4 = std::make_shared<PhysicalProject>(p4_expressions);
    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {1};
    std::vector<LogicalType> key_types = {LogicalType::DOUBLE};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(project4);
    project4->AddChild(join5);
    join5->AddChild(project2);
    join5->AddChild(hashAgg2);
    project2->AddChild(hashAgg1);
    hashAgg1->AddChild(project1);
    project1->AddChild(join2);
    join2->AddChild(join1);
    join2->AddChild(scan_partsupp1);
    join1->AddChild(filter1);
    join1->AddChild(scan_supplier1);
    filter1->AddChild(scan_nation1);
    hashAgg2->AddChild(project3);
    project3->AddChild(join4);
    join4->AddChild(join3);
    join4->AddChild(scan_partsupp2);
    join3->AddChild(filter2);
    join3->AddChild(scan_supplier2);
    filter2->AddChild(scan_nation2);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q11执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q11查询
TEST(TPCHTest, Q11FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    std::vector<std::string> nation_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "nation.tbl_" + std::to_string(i);
        nation_file_names.emplace_back(file_name);
    }
    InsertNationMul(table_nation, scheduler, work_ids, partition_idxs, nation_file_names);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    std::vector<std::string> supplier_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "supplier.tbl_" + std::to_string(i);
        supplier_file_names.emplace_back(file_name);
    }
    InsertSupplierMul(table_supplier, scheduler, work_ids, partition_idxs, supplier_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    // 插入Partsupp表数据
    std::shared_ptr<Table> table_partsupp;
    std::vector<std::string> partsupp_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "partsupp.tbl_" + std::to_string(i);
        partsupp_file_names.emplace_back(file_name);
    }
    InsertPartsuppMul(table_partsupp, scheduler, work_ids, partition_idxs, partsupp_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertPartsupp Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> nation_ids = {0, 1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation1 = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);
    std::shared_ptr<PhysicalTableScan> scan_nation2 = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> supplier_ids = {0, 3};
    // <s_suppkey, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier1 = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);
    std::shared_ptr<PhysicalTableScan> scan_supplier2 = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    std::vector<int> partsupp_ids = {1, 2, 3};
    // <ps_suppkey, ps_availqty, ps_supplycost>
    std::shared_ptr<PhysicalTableScan> scan_partsupp1 = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);

    std::vector<int> partsupp_ids2 = {0, 1, 2, 3};
    // <ps_partkey, ps_suppkey, ps_availqty, ps_supplycost>
    std::shared_ptr<PhysicalTableScan> scan_partsupp2 = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids2);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_GERMANY("GERMANY");
    std::shared_ptr<BoundConstantExpression> right_constant = std::make_shared<BoundConstantExpression>(value_GERMANY);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_n_name = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_n_name->SetLeft(f1_n_name);
    comparisonExpression_n_name->SetRight(right_constant);
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(comparisonExpression_n_name);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {1};
    // <s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join1->exp_name = "1";

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {0};
    // <ps_suppkey, ps_availqty, ps_supplycost, s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join2->exp_name = "2";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_ps_availqty = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::vector<LogicalType> p1_arguments = { LogicalType::FLOAT, LogicalType::INTEGER };
    scalar_function_p p1_function = GetMulFunction();
    ScalarProjectFunction p1_bound_function("*", p1_arguments, LogicalType::FLOAT, p1_function, nullptr);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_ps_supplycost, p1_ps_availqty};
    std::shared_ptr<BoundProjectFunctionExpression> p1_alias = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p1_bound_function, p1_expressions, nullptr);
    p1_alias->alias = "ps_supplycost * ps_availqty";

    std::vector<std::shared_ptr<Expression>> p1_expressions2 = {p1_alias};
    // <(ps_supplycost * ps_availqty)>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions2);
    project1->exp_name = "1";

    //  ================================================构建HashAgg================================================
    std::vector<int> agg_set = {0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM};
    // <Sum(ps_supplycost * ps_availqty)>
    std::shared_ptr<PhysicalHashAgg> hashAgg1 = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, agg_set);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p2_sum = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 0, 0);
    Value value_00001(0.0001);
    std::shared_ptr<BoundConstantExpression> p2_constant = std::make_shared<BoundConstantExpression>(value_00001);
    std::vector<LogicalType> p2_arguments = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p p2_function = GetMulFunction();
    ScalarProjectFunction p2_bound_function("*", p2_arguments, LogicalType::DOUBLE, p2_function, nullptr);
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_sum, p2_constant};
    std::shared_ptr<BoundProjectFunctionExpression> p2_alias = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p2_bound_function, p2_expressions, nullptr);
    p2_alias->alias = "Sum(ps_supplycost * ps_availqty) * 0.0001";

    std::vector<std::shared_ptr<Expression>> p2_expressions2 = {p2_alias};
    // <Sum(ps_supplycost * ps_availqty) * 0.0001>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions2);
    project2->exp_name = "2";
    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f2_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundConstantExpression> right_constant2 = std::make_shared<BoundConstantExpression>(value_GERMANY);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_n_name2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    comparisonExpression_n_name2->SetLeft(f2_n_name);
    comparisonExpression_n_name2->SetRight(right_constant2);
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(comparisonExpression_n_name2);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids3 = {0};
    std::vector<int> prode_ids3 = {1};
    // <s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join3 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    join3->exp_name = "3";

    std::vector<int> build_ids4 = {0};
    std::vector<int> prode_ids4 = {1};
    // <ps_partkey, ps_suppkey, ps_availqty, ps_supplycost, s_suppkey, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join4 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);
    join4->exp_name = "4";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p3_ps_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_ps_supplycost = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_ps_availqty = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::vector<LogicalType> p3_arguments = { LogicalType::FLOAT, LogicalType::INTEGER };
    scalar_function_p p3_function = GetMulFunction();
    ScalarProjectFunction p3_bound_function("*", p3_arguments, LogicalType::FLOAT, p3_function, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions = {p3_ps_supplycost, p3_ps_availqty};
    std::shared_ptr<BoundProjectFunctionExpression> p3_alias = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p3_bound_function, p3_expressions, nullptr);
    p3_alias->alias = "ps_supplycost * ps_availqty";

    std::vector<std::shared_ptr<Expression>> p3_expressions2 = {p3_ps_partkey, p3_alias};
    // <ps_partkey, (ps_supplycost * ps_availqty)>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions2);
    project3->exp_name = "3";
    // 构建HashAgg
    std::vector<int> group_set2 = {0};
    std::vector<int> agg_set2 = {1};
    std::vector<int> star_bitmap2 = {0};
    std::vector<AggFunctionType> aggregate_function_types2 = {AggFunctionType::SUM};
    // <ps_partkey, Sum(ps_supplycost * ps_availqty)-value>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg2 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set2, agg_set2, star_bitmap2, aggregate_function_types2);

    //  ================================================构建NestLoopJoin================================================
    std::vector<int> build_ids5 = {0};
    std::vector<int> prode_ids5 = {1};
    std::vector<ExpressionTypes> compare_types = { ExpressionTypes::COMPARE_GREATERTHAN };
    // <ps_partkey, Sum(ps_supplycost * ps_availqty)-value, Sum(ps_supplycost * ps_availqty) * 0.0001>
    std::shared_ptr<PhysicalNestedLoopJoin> join5 = std::make_shared<PhysicalNestedLoopJoin>(JoinTypes::INNER, build_ids5, prode_ids5, compare_types);
    join5->exp_name = "5";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p4_ps_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p4_value = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p4_expressions = {p4_ps_partkey, p4_value};
    // <ps_partkey, value>
    std::shared_ptr<PhysicalProject> project4 = std::make_shared<PhysicalProject>(p4_expressions);
    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {1};
    std::vector<LogicalType> key_types = {LogicalType::DOUBLE};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(project4);
    project4->AddChild(join5);
    join5->AddChild(project2);
    join5->AddChild(hashAgg2);
    project2->AddChild(hashAgg1);
    hashAgg1->AddChild(project1);
    project1->AddChild(join2);
    join2->AddChild(join1);
    join2->AddChild(scan_partsupp1);
    join1->AddChild(filter1);
    join1->AddChild(scan_supplier1);
    filter1->AddChild(scan_nation1);
    hashAgg2->AddChild(project3);
    project3->AddChild(join4);
    join4->AddChild(join3);
    join4->AddChild(scan_partsupp2);
    join3->AddChild(filter2);
    join3->AddChild(scan_supplier2);
    filter2->AddChild(scan_nation2);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q11执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q12=============================
// 测试单线程Q12查询
TEST(TPCHTest, Q12SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    InsertOrders(table_orders, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> lineitem_ids = {0, 10, 11, 12, 14};
    // <l_orderkey, l_shipdate, l_commitdate, l_receiptdate, l_shipmode>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> orders_ids = {0, 5};
    // <o_orderkey, o_orderpriority>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_l_receiptdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_757353600(757353600);
    std::shared_ptr<BoundConstantExpression> f1_right_constant = std::make_shared<BoundConstantExpression>(value_757353600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_receiptdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_l_receiptdate->SetLeft(f1_l_receiptdate);
    comparisonExpression_l_receiptdate->SetRight(f1_right_constant);

    std::shared_ptr<BoundColumnRefExpression> f1_l_receiptdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_788889600(788889600);
    std::shared_ptr<BoundConstantExpression> f1_right_constant2 = std::make_shared<BoundConstantExpression>(value_788889600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_receiptdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_receiptdate2->SetLeft(f1_l_receiptdate2);
    comparisonExpression_l_receiptdate2->SetRight(f1_right_constant2);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_and1 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_l_receiptdate, comparisonExpression_l_receiptdate2);

    std::shared_ptr<BoundColumnRefExpression> f1_l_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_shipdate->SetLeft(f1_l_shipdate);
    comparisonExpression_l_shipdate->SetRight(f1_right_constant2);
    std::shared_ptr<BoundColumnRefExpression> f1_l_commitdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_commitdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_commitdate->SetLeft(f1_l_commitdate);
    comparisonExpression_l_commitdate->SetRight(f1_right_constant2);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_and2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_l_shipdate, comparisonExpression_l_commitdate);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_and3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, conjunctionExpression_and1, conjunctionExpression_and2);
    // <l_orderkey, l_shipdate, l_commitdate, l_receiptdate, l_shipmode>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(conjunctionExpression_and3);

    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_commitdate_receiptdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_commitdate_receiptdate->SetLeft(f1_l_commitdate);
    comparisonExpression_l_commitdate_receiptdate->SetRight(f1_l_receiptdate);

    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate_commitdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_shipdate_commitdate->SetLeft(f1_l_shipdate);
    comparisonExpression_l_shipdate_commitdate->SetRight(f1_l_commitdate);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_and4 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_l_commitdate_receiptdate, comparisonExpression_l_shipdate_commitdate);

    Value value_MAIL("MAIL");
    Value value_SHIP("SHIP");
    std::vector<Value> value_set = {value_MAIL, value_SHIP};
    std::shared_ptr<BoundColumnRefExpression> f2_l_shipmode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 4, 0);
    std::shared_ptr<BoundInExpression> inExpression = std::make_shared<BoundInExpression>(f2_l_shipmode, value_set, LogicalType::STRING);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_and5 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, conjunctionExpression_and4, inExpression);
    // <l_orderkey, l_shipdate, l_commitdate, l_receiptdate, l_shipmode>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(conjunctionExpression_and5);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_l_orderkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_shipmode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 4, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_l_orderkey, p1_l_shipmode};
    // <l_orderkey, l_shipmode>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {0};
    // <o_orderkey, o_orderpriority, l_orderkey, l_shipmode>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join1->exp_name = "1";

    //  =============================================构建case-when Project=============================================
    std::shared_ptr<BoundColumnRefExpression> p2_l_shipmode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_o_orderpriority = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_URGENT("1-URGENT");
    std::shared_ptr<BoundConstantExpression> p2_constant_col = std::make_shared<BoundConstantExpression>(value_URGENT);
    Value value_HIGH("2-HIGH");
    std::shared_ptr<BoundConstantExpression> p2_constant_col2 = std::make_shared<BoundConstantExpression>(value_HIGH);

    Value value_0(0);
    std::shared_ptr<BoundConstantExpression> p2_constant0_col = std::make_shared<BoundConstantExpression>(value_0);
    Value value_1(1);
    std::shared_ptr<BoundConstantExpression> p2_constant1_col = std::make_shared<BoundConstantExpression>(value_1);

    std::shared_ptr<BoundComparisonExpression> p2_when_expr1 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    p2_when_expr1->SetLeft(p2_o_orderpriority);
    p2_when_expr1->SetRight(p2_constant_col);
    std::shared_ptr<BoundComparisonExpression> p2_when_expr2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    p2_when_expr2->SetLeft(p2_o_orderpriority);
    p2_when_expr2->SetRight(p2_constant_col2);

    std::shared_ptr<BoundConjunctionExpression> p2_when_expr3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_OR, p2_when_expr1, p2_when_expr2);

    std::shared_ptr<BoundCaseExpression> case_expr1 = std::make_shared<BoundCaseExpression>();
    case_expr1->SetWhenExpr(p2_when_expr3);
    case_expr1->SetThenExpr(p2_constant1_col);
    case_expr1->SetElseExpr(p2_constant0_col);
    case_expr1->alias = "high_line_count";

    std::shared_ptr<BoundComparisonExpression> p2_when_expr4 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_NOTEQUAL);
    p2_when_expr4->SetLeft(p2_o_orderpriority);
    p2_when_expr4->SetRight(p2_constant_col);
    std::shared_ptr<BoundComparisonExpression> p2_when_expr5 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_NOTEQUAL);
    p2_when_expr5->SetLeft(p2_o_orderpriority);
    p2_when_expr5->SetRight(p2_constant_col2);
    std::shared_ptr<BoundConjunctionExpression> p2_when_expr6 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, p2_when_expr4, p2_when_expr5);

    std::shared_ptr<BoundCaseExpression> case_expr2 = std::make_shared<BoundCaseExpression>();
    case_expr2->SetWhenExpr(p2_when_expr6);
    case_expr2->SetThenExpr(p2_constant1_col);
    case_expr2->SetElseExpr(p2_constant0_col);
    case_expr2->alias = "low_line_count";

    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_l_shipmode, case_expr1, case_expr2};
    // <l_shipmode, high_line_count, low_line_count>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    //  ================================================构建HashAgg================================================
    std::vector<int> group_set = {0};
    std::vector<int> agg_set = {1, 2};
    std::vector<int> star_bitmap = {0, 0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM, AggFunctionType::SUM};
    // <l_shipmode, Sum(high_line_count), Sum(low_line_count)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::STRING};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project2);
    project2->AddChild(join1);
    join1->AddChild(project1);
    join1->AddChild(scan_orders);
    project1->AddChild(filter2);
    filter2->AddChild(filter1);
    filter1->AddChild(scan_lineitem);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q12执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q12查询
TEST(TPCHTest, Q12FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> lineitem_ids = {0, 10, 11, 12, 14};
    // <l_orderkey, l_shipdate, l_commitdate, l_receiptdate, l_shipmode>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> orders_ids = {0, 5};
    // <o_orderkey, o_orderpriority>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_l_receiptdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_757353600(757353600);
    std::shared_ptr<BoundConstantExpression> f1_right_constant = std::make_shared<BoundConstantExpression>(value_757353600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_receiptdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_l_receiptdate->SetLeft(f1_l_receiptdate);
    comparisonExpression_l_receiptdate->SetRight(f1_right_constant);

    std::shared_ptr<BoundColumnRefExpression> f1_l_receiptdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_788889600(788889600);
    std::shared_ptr<BoundConstantExpression> f1_right_constant2 = std::make_shared<BoundConstantExpression>(value_788889600);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_receiptdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_receiptdate2->SetLeft(f1_l_receiptdate2);
    comparisonExpression_l_receiptdate2->SetRight(f1_right_constant2);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_and1 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_l_receiptdate, comparisonExpression_l_receiptdate2);

    std::shared_ptr<BoundColumnRefExpression> f1_l_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_shipdate->SetLeft(f1_l_shipdate);
    comparisonExpression_l_shipdate->SetRight(f1_right_constant2);
    std::shared_ptr<BoundColumnRefExpression> f1_l_commitdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_commitdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_commitdate->SetLeft(f1_l_commitdate);
    comparisonExpression_l_commitdate->SetRight(f1_right_constant2);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_and2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_l_shipdate, comparisonExpression_l_commitdate);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_and3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, conjunctionExpression_and1, conjunctionExpression_and2);
    // <l_orderkey, l_shipdate, l_commitdate, l_receiptdate, l_shipmode>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(conjunctionExpression_and3);

    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_commitdate_receiptdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_commitdate_receiptdate->SetLeft(f1_l_commitdate);
    comparisonExpression_l_commitdate_receiptdate->SetRight(f1_l_receiptdate);

    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate_commitdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_shipdate_commitdate->SetLeft(f1_l_shipdate);
    comparisonExpression_l_shipdate_commitdate->SetRight(f1_l_commitdate);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_and4 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_l_commitdate_receiptdate, comparisonExpression_l_shipdate_commitdate);

    Value value_MAIL("MAIL");
    Value value_SHIP("SHIP");
    std::vector<Value> value_set = {value_MAIL, value_SHIP};
    std::shared_ptr<BoundColumnRefExpression> f2_l_shipmode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 4, 0);
    std::shared_ptr<BoundInExpression> inExpression = std::make_shared<BoundInExpression>(f2_l_shipmode, value_set, LogicalType::STRING);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_and5 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, conjunctionExpression_and4, inExpression);
    // <l_orderkey, l_shipdate, l_commitdate, l_receiptdate, l_shipmode>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(conjunctionExpression_and5);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_l_orderkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_shipmode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 4, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_l_orderkey, p1_l_shipmode};
    // <l_orderkey, l_shipmode>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {0};
    // <o_orderkey, o_orderpriority, l_orderkey, l_shipmode>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join1->exp_name = "1";

    //  =============================================构建case-when Project=============================================
    std::shared_ptr<BoundColumnRefExpression> p2_l_shipmode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_o_orderpriority = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_URGENT("1-URGENT");
    std::shared_ptr<BoundConstantExpression> p2_constant_col = std::make_shared<BoundConstantExpression>(value_URGENT);
    Value value_HIGH("2-HIGH");
    std::shared_ptr<BoundConstantExpression> p2_constant_col2 = std::make_shared<BoundConstantExpression>(value_HIGH);

    Value value_0(0);
    std::shared_ptr<BoundConstantExpression> p2_constant0_col = std::make_shared<BoundConstantExpression>(value_0);
    Value value_1(1);
    std::shared_ptr<BoundConstantExpression> p2_constant1_col = std::make_shared<BoundConstantExpression>(value_1);

    std::shared_ptr<BoundComparisonExpression> p2_when_expr1 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    p2_when_expr1->SetLeft(p2_o_orderpriority);
    p2_when_expr1->SetRight(p2_constant_col);
    std::shared_ptr<BoundComparisonExpression> p2_when_expr2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL);
    p2_when_expr2->SetLeft(p2_o_orderpriority);
    p2_when_expr2->SetRight(p2_constant_col2);

    std::shared_ptr<BoundConjunctionExpression> p2_when_expr3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_OR, p2_when_expr1, p2_when_expr2);

    std::shared_ptr<BoundCaseExpression> case_expr1 = std::make_shared<BoundCaseExpression>();
    case_expr1->SetWhenExpr(p2_when_expr3);
    case_expr1->SetThenExpr(p2_constant1_col);
    case_expr1->SetElseExpr(p2_constant0_col);
    case_expr1->alias = "high_line_count";

    std::shared_ptr<BoundComparisonExpression> p2_when_expr4 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_NOTEQUAL);
    p2_when_expr4->SetLeft(p2_o_orderpriority);
    p2_when_expr4->SetRight(p2_constant_col);
    std::shared_ptr<BoundComparisonExpression> p2_when_expr5 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_NOTEQUAL);
    p2_when_expr5->SetLeft(p2_o_orderpriority);
    p2_when_expr5->SetRight(p2_constant_col2);
    std::shared_ptr<BoundConjunctionExpression> p2_when_expr6 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, p2_when_expr4, p2_when_expr5);

    std::shared_ptr<BoundCaseExpression> case_expr2 = std::make_shared<BoundCaseExpression>();
    case_expr2->SetWhenExpr(p2_when_expr6);
    case_expr2->SetThenExpr(p2_constant1_col);
    case_expr2->SetElseExpr(p2_constant0_col);
    case_expr2->alias = "low_line_count";

    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_l_shipmode, case_expr1, case_expr2};
    // <l_shipmode, high_line_count, low_line_count>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    //  ================================================构建HashAgg================================================
    std::vector<int> group_set = {0};
    std::vector<int> agg_set = {1, 2};
    std::vector<int> star_bitmap = {0, 0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM, AggFunctionType::SUM};
    // <l_shipmode, Sum(high_line_count), Sum(low_line_count)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::STRING};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project2);
    project2->AddChild(join1);
    join1->AddChild(project1);
    join1->AddChild(scan_orders);
    project1->AddChild(filter2);
    filter2->AddChild(filter1);
    filter1->AddChild(scan_lineitem);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q12执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q13=============================
// 注意修改数据文件路径
TEST(TPCHTest, Q13SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    Util::print_socket_free_memory();
    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    InsertCustomer(table_customer, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);
    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    InsertOrders(table_orders, scheduler);
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);
    Util::print_socket_free_memory();
    //  ================================================构建Scan================================================
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders);
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer);

    //  ================================================构建Filter================================================
    // 构建Filter表达式  o_comment NOT LIKE '%pending%deposits%'
    std::shared_ptr<BoundColumnRefExpression> left_comment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 8, 0);
    std::string like_pattern = "%pending%deposits%";
    ScalarFunction bound_function = NotLikeFun::GetNotLikeFunction();
    Value value_pattern(like_pattern);
    std::shared_ptr<BoundConstantExpression> right_comment = std::make_shared<BoundConstantExpression>(value_pattern);
    std::vector<std::shared_ptr<Expression>> arguments;
    arguments.push_back(std::move(left_comment));
    arguments.push_back(std::move(right_comment));
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments, nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);
    std::shared_ptr<PhysicalFilter> filter = std::make_shared<PhysicalFilter>(functionExpression);

    //  ================================================构建HashJoin_LEFT================================================
    std::vector<int> build_ids = {1};
    std::vector<int> prode_ids = {0};
    std::shared_ptr<PhysicalHashJoin> join = std::make_shared<PhysicalHashJoin>(JoinTypes::LEFT, build_ids, prode_ids);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> custkey_col = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> orderkey_col = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 8, 0);
    std::vector<std::shared_ptr<Expression>> expressions = {custkey_col, orderkey_col};
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(expressions);

    //  ================================================构建HashAgg================================================
    //const std::vector<AggFunctionType> &aggregate_function_types_,
    //                    const std::vector<int32_t> &group_item_idxs_
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::COUNT };
    std::vector<int32_t> group_item_idxs = { 1 };
    std::shared_ptr<PhysicalHashAgg> hashAgg1 = std::make_shared<PhysicalHashAgg>(0, aggregate_function_types, group_item_idxs);
    std::vector<int32_t> group_item_idxs2 = { 1 };
    std::shared_ptr<PhysicalHashAgg> hashAgg2 = std::make_shared<PhysicalHashAgg>(1, aggregate_function_types, group_item_idxs2);
    hashAgg2->is_star = true;
    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::INTEGER};
    std::vector<SortOrder> orders = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders);
    orderby->AddChild(hashAgg2);
    hashAgg2->AddChild(hashAgg1);
    hashAgg1->AddChild(project);
    project->AddChild(join);
    join->AddChild(filter);
    join->AddChild(scan_customer);
    filter->AddChild(scan_orders);
    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q13执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

TEST(TPCHTest, Q13TwoThreadTest) {
    ////// step-1：构造表数据，分别往分区1和分区20插入数据
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    Util::print_socket_free_memory();
    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    std::vector<int> work_ids = {1, 2};
    std::vector<int> partition_idxs = {1, 2};
    std::vector<std::string> customer_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir2 + "/" + "customer.tbl_" + std::to_string(i);
        customer_file_names.emplace_back(file_name);
    }
    InsertCustomerMul(table_customer, scheduler, work_ids, partition_idxs, customer_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);
    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir2 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    std::this_thread::sleep_for(std::chrono::seconds(5));
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);
    Util::print_socket_free_memory();
    //  ================================================构建Scan================================================
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders);
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer);

    //  ================================================构建Filter================================================
    // 构建Filter表达式  o_comment NOT LIKE '%pending%deposits%'
    std::shared_ptr<BoundColumnRefExpression> left_comment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 8, 0);
    std::string like_pattern = "%pending%deposits%";
    ScalarFunction bound_function = NotLikeFun::GetNotLikeFunction();
    Value value_pattern(like_pattern);
    std::shared_ptr<BoundConstantExpression> right_comment = std::make_shared<BoundConstantExpression>(value_pattern);
    std::vector<std::shared_ptr<Expression>> arguments;
    arguments.push_back(std::move(left_comment));
    arguments.push_back(std::move(right_comment));
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments, nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);
    std::shared_ptr<PhysicalFilter> filter = std::make_shared<PhysicalFilter>(functionExpression);

    //  ================================================构建HashJoin_LEFT================================================
    std::vector<int> build_ids = {1};
    std::vector<int> prode_ids = {0};
    std::shared_ptr<PhysicalHashJoin> join = std::make_shared<PhysicalHashJoin>(JoinTypes::LEFT, build_ids, prode_ids);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> custkey_col = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> orderkey_col = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 8, 0);
    std::vector<std::shared_ptr<Expression>> expressions = {custkey_col, orderkey_col};
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(expressions);

    //  ================================================构建HashAgg================================================
    //const std::vector<AggFunctionType> &aggregate_function_types_,
    //                    const std::vector<int32_t> &group_item_idxs_
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::COUNT };
    std::vector<int32_t> group_item_idxs = { 1 };
    std::shared_ptr<PhysicalHashAgg> hashAgg1 = std::make_shared<PhysicalHashAgg>(0, aggregate_function_types, group_item_idxs);
    std::vector<int32_t> group_item_idxs2 = { 0 };
    std::shared_ptr<PhysicalHashAgg> hashAgg2 = std::make_shared<PhysicalHashAgg>(1, aggregate_function_types, group_item_idxs2);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::INTEGER, LogicalType::INTEGER};
    std::vector<SortOrder> orders = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders);
    orderby->AddChild(hashAgg2);
    hashAgg2->AddChild(hashAgg1);
    hashAgg1->AddChild(project);
    project->AddChild(join);
    join->AddChild(filter);
    join->AddChild(scan_customer);
    filter->AddChild(scan_orders);
    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q13执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

TEST(TPCHTest, Q13FourThreadTest) {
    ////// step-1：构造表数据，分别往分区1和分区20插入数据
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    Util::print_socket_free_memory();
    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    std::vector<std::string> customer_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "customer.tbl_" + std::to_string(i);
        customer_file_names.emplace_back(file_name);
    }
    InsertCustomerMul(table_customer, scheduler, work_ids, partition_idxs, customer_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);
    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    std::this_thread::sleep_for(std::chrono::seconds(5));
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);
    Util::print_socket_free_memory();
    //  ================================================构建Scan================================================
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders);
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer);

    //  ================================================构建Filter================================================
    // 构建Filter表达式  o_comment NOT LIKE '%pending%deposits%'
    std::shared_ptr<BoundColumnRefExpression> left_comment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 8, 0);
    std::string like_pattern = "%pending%deposits%";
    ScalarFunction bound_function = NotLikeFun::GetNotLikeFunction();
    Value value_pattern(like_pattern);
    std::shared_ptr<BoundConstantExpression> right_comment = std::make_shared<BoundConstantExpression>(value_pattern);
    std::vector<std::shared_ptr<Expression>> arguments;
    arguments.push_back(std::move(left_comment));
    arguments.push_back(std::move(right_comment));
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments, nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);
    std::shared_ptr<PhysicalFilter> filter = std::make_shared<PhysicalFilter>(functionExpression);

    //  ================================================构建HashJoin_LEFT================================================
    std::vector<int> build_ids = {1};
    std::vector<int> prode_ids = {0};
    std::shared_ptr<PhysicalHashJoin> join = std::make_shared<PhysicalHashJoin>(JoinTypes::LEFT, build_ids, prode_ids);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> custkey_col = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> orderkey_col = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 8, 0);
    std::vector<std::shared_ptr<Expression>> expressions = {custkey_col, orderkey_col};
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(expressions);

    //  ================================================构建HashAgg================================================
    //const std::vector<AggFunctionType> &aggregate_function_types_,
    //                    const std::vector<int32_t> &group_item_idxs_
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::COUNT };
    std::vector<int32_t> group_item_idxs = { 1 };
    std::shared_ptr<PhysicalHashAgg> hashAgg1 = std::make_shared<PhysicalHashAgg>(0, aggregate_function_types, group_item_idxs);
    std::vector<int32_t> group_item_idxs2 = { 0 };
    std::shared_ptr<PhysicalHashAgg> hashAgg2 = std::make_shared<PhysicalHashAgg>(1, aggregate_function_types, group_item_idxs2);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::INTEGER, LogicalType::INTEGER};
    std::vector<SortOrder> orders = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders);
    orderby->AddChild(hashAgg2);
    hashAgg2->AddChild(hashAgg1);
    hashAgg1->AddChild(project);
    project->AddChild(join);
    join->AddChild(filter);
    join->AddChild(scan_customer);
    filter->AddChild(scan_orders);
    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q13执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 优化查询计划
TEST(TPCHTest, Q13FourThreadTest2) {
    ////// step-1：构造表数据，分别往分区1和分区20插入数据
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    Util::print_socket_free_memory();
    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    std::vector<std::string> customer_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "customer.tbl_" + std::to_string(i);
        customer_file_names.emplace_back(file_name);
    }
    InsertCustomerMul(table_customer, scheduler, work_ids, partition_idxs, customer_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);
    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    std::this_thread::sleep_for(std::chrono::seconds(5));
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);
    Util::print_socket_free_memory();
    //  ================================================构建Scan================================================
    std::vector<int> projection_ids1 = {0, 1, 8};
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, projection_ids1);
    std::vector<int> projection_ids2 = {0};
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer, -1, projection_ids2);

    //  ================================================构建Filter================================================
    // 构建Filter表达式  o_comment NOT LIKE '%pending%deposits%'
    std::shared_ptr<BoundColumnRefExpression> left_comment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);
    std::string like_pattern = "%pending%deposits%";
    ScalarFunction bound_function = NotLikeFun::GetNotLikeFunction();
    Value value_pattern(like_pattern);
    std::shared_ptr<BoundConstantExpression> right_comment = std::make_shared<BoundConstantExpression>(value_pattern);
    std::vector<std::shared_ptr<Expression>> arguments;
    arguments.push_back(std::move(left_comment));
    arguments.push_back(std::move(right_comment));
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments, nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);
    std::shared_ptr<PhysicalFilter> filter = std::make_shared<PhysicalFilter>(functionExpression);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> custkey_col = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> orderkey_col = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> expressions = {custkey_col, orderkey_col};
    std::shared_ptr<PhysicalProject> project = std::make_shared<PhysicalProject>(expressions);

    //  ================================================构建HashJoin_LEFT================================================
    std::vector<int> build_ids = {1};
    std::vector<int> prode_ids = {0};
    std::shared_ptr<PhysicalHashJoin> join = std::make_shared<PhysicalHashJoin>(JoinTypes::LEFT, build_ids, prode_ids);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> c_custkey_col = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> o_orderkey_col = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::vector<std::shared_ptr<Expression>> expressions2 = {c_custkey_col, o_orderkey_col};
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(expressions2);

    //  ================================================构建HashAgg================================================
    //const std::vector<AggFunctionType> &aggregate_function_types_,
    //                    const std::vector<int32_t> &group_item_idxs_
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::COUNT };
    std::vector<int32_t> group_item_idxs = { 1 };
    std::shared_ptr<PhysicalHashAgg> hashAgg1 = std::make_shared<PhysicalHashAgg>(0, aggregate_function_types, group_item_idxs);
    std::vector<int32_t> group_item_idxs2 = { 1 };
    std::shared_ptr<PhysicalHashAgg> hashAgg2 = std::make_shared<PhysicalHashAgg>(1, aggregate_function_types, group_item_idxs2);
    hashAgg2->is_star = true;
    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::INTEGER};
    std::vector<SortOrder> orders = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders);
    orderby->AddChild(hashAgg2);
    hashAgg2->AddChild(hashAgg1);
    hashAgg1->AddChild(project2);
    project2->AddChild(join);
    join->AddChild(project);
    join->AddChild(scan_customer);
    project->AddChild(filter);
    filter->AddChild(scan_orders);
    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q13执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q14=============================
// 测试单线程Q14查询
TEST(TPCHTest, Q14SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    InsertPart(table_part, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> lineitem_ids = {1, 5, 6, 10};
    // <l_partkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> part_ids = {0, 4};
    // <p_partkey, p_type>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_l_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_809884800(809884800);
    std::shared_ptr<BoundConstantExpression> f1_right_constant = std::make_shared<BoundConstantExpression>(value_809884800);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_l_shipdate->SetLeft(f1_l_shipdate);
    comparisonExpression_l_shipdate->SetRight(f1_right_constant);

    std::shared_ptr<BoundColumnRefExpression> f1_l_shipdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_812476800(812476800);
    std::shared_ptr<BoundConstantExpression> f1_right_constant2 = std::make_shared<BoundConstantExpression>(value_812476800);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_shipdate2->SetLeft(f1_l_shipdate2);
    comparisonExpression_l_shipdate2->SetRight(f1_right_constant2);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_and1 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_l_shipdate, comparisonExpression_l_shipdate2);

    // <l_partkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(conjunctionExpression_and1);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {0};
    // <l_partkey, l_extendedprice, l_discount, l_shipdate, p_partkey, p_type>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join1->exp_name = "1";

    //  =============================================构建case-when Project=============================================
    std::shared_ptr<BoundColumnRefExpression> p1_p_type = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::string like_pattern = "PROMO%";
    Value value(like_pattern);
    std::shared_ptr<BoundConstantExpression> p1_constant_col = std::make_shared<BoundConstantExpression>(value);
    ScalarFunction bound_function = LikeFun::GetLikeFunction();
    std::vector<std::shared_ptr<Expression>> arguments = {p1_p_type, p1_constant_col};
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments,nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);

    std::vector<LogicalType> arguments1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function1 = GetSubFunction();
    ScalarProjectFunction bound_function1("-", arguments1, LogicalType::FLOAT, function1, nullptr);
    Value value_1(1.0F);
    std::shared_ptr<BoundConstantExpression> constant1_col = std::make_shared<BoundConstantExpression>(value_1);
    std::vector<std::shared_ptr<Expression>> expressions1 = {constant1_col, p1_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function1, expressions1, nullptr);
    discount_1_col->alias = "1-l_discount";

    std::vector<LogicalType> arguments2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function2 = GetMulFunction();
    ScalarProjectFunction bound_function2("*", arguments2, LogicalType::FLOAT, function2, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions2 = {p1_l_extendedprice, discount_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function2, expressions2, nullptr);
    extendedprice_discount_1_col->alias = "l_extendedprice*(1-l_discount)";

    Value value_0(0.0F);
    std::shared_ptr<BoundConstantExpression> p1_constant0_col = std::make_shared<BoundConstantExpression>(value_0);
    std::shared_ptr<BoundCaseExpression> case_expr1 = std::make_shared<BoundCaseExpression>();
    case_expr1->SetWhenExpr(functionExpression);
    case_expr1->SetThenExpr(extendedprice_discount_1_col);
    case_expr1->SetElseExpr(p1_constant0_col);
    case_expr1->alias = "case-1";

    std::vector<std::shared_ptr<Expression>> p1_expressions = {case_expr1, extendedprice_discount_1_col};
    // <case-1, l_extendedprice*(1-l_discount)>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建HashAgg================================================
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::SUM, AggFunctionType::SUM };
    std::vector<int32_t> group_item_idxs = { 0, 1 };
    // <Sum(case-1), Sum(l_extendedprice*(1-l_discount))>
    std::shared_ptr<PhysicalHashAgg> hashAgg1 = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, group_item_idxs);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p2_case_1 = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_sum_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 1, 0);
    std::vector<LogicalType> p2_arguments = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p p2_function = GetMulFunction();
    ScalarProjectFunction p2_bound_function("*", p2_arguments, LogicalType::DOUBLE, p2_function, nullptr);
    Value value_100d(100.0);
    std::shared_ptr<BoundConstantExpression> p2_constant100d_col = std::make_shared<BoundConstantExpression>(value_100d);
    std::vector<std::shared_ptr<Expression>> p2_expressions1 = {p2_constant100d_col, p2_case_1};
    std::shared_ptr<BoundProjectFunctionExpression> col_1 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::DOUBLE, p2_bound_function, p2_expressions1, nullptr);
    col_1->alias = "100.00*case_1";

    std::vector<LogicalType> p2_arguments2 = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p p2_function2 = GetDivFunction();
    ScalarProjectFunction p2_bound_function2("/", p2_arguments2, LogicalType::DOUBLE, p2_function2, nullptr);
    std::vector<std::shared_ptr<Expression>>p2_expressions2 = {col_1, p2_sum_2};
    std::shared_ptr<BoundProjectFunctionExpression> col_2 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::DOUBLE, p2_bound_function2, p2_expressions2, nullptr);
    col_2->alias = "promo_revenue";
    std::vector<std::shared_ptr<Expression>> p2_expressions3 = {col_2};
    // <promo_revenue>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions3);
    project2->exp_name = "2";
    std::shared_ptr<PhysicalResultCollector> result_collector = std::make_shared<PhysicalResultCollector>(project2);
    result_collector->AddChild(project2);
    project2->AddChild(hashAgg1);
    hashAgg1->AddChild(project1);
    project1->AddChild(join1);
    join1->AddChild(scan_part);
    join1->AddChild(filter1);
    filter1->AddChild(scan_lineitem);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    result_collector->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q14执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q14查询
TEST(TPCHTest, Q14FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    std::vector<std::string> part_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "part.tbl_" + std::to_string(i);
        part_file_names.emplace_back(file_name);
    }
    InsertPartMul(table_part, scheduler, work_ids, partition_idxs, part_file_names);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> lineitem_ids = {1, 5, 6, 10};
    // <l_partkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> part_ids = {0, 4};
    // <p_partkey, p_type>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_l_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_809884800(809884800);
    std::shared_ptr<BoundConstantExpression> f1_right_constant = std::make_shared<BoundConstantExpression>(value_809884800);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO);
    comparisonExpression_l_shipdate->SetLeft(f1_l_shipdate);
    comparisonExpression_l_shipdate->SetRight(f1_right_constant);

    std::shared_ptr<BoundColumnRefExpression> f1_l_shipdate2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_812476800(812476800);
    std::shared_ptr<BoundConstantExpression> f1_right_constant2 = std::make_shared<BoundConstantExpression>(value_812476800);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression_l_shipdate2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN);
    comparisonExpression_l_shipdate2->SetLeft(f1_l_shipdate2);
    comparisonExpression_l_shipdate2->SetRight(f1_right_constant2);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression_and1 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression_l_shipdate, comparisonExpression_l_shipdate2);

    // <l_partkey, l_extendedprice, l_discount, l_shipdate>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(conjunctionExpression_and1);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {0};
    // <l_partkey, l_extendedprice, l_discount, l_shipdate, p_partkey, p_type>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join1->exp_name = "1";

    //  =============================================构建case-when Project=============================================
    std::shared_ptr<BoundColumnRefExpression> p1_p_type = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::string like_pattern = "PROMO%";
    Value value(like_pattern);
    std::shared_ptr<BoundConstantExpression> p1_constant_col = std::make_shared<BoundConstantExpression>(value);
    ScalarFunction bound_function = LikeFun::GetLikeFunction();
    std::vector<std::shared_ptr<Expression>> arguments = {p1_p_type, p1_constant_col};
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments,nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);

    std::vector<LogicalType> arguments1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function1 = GetSubFunction();
    ScalarProjectFunction bound_function1("-", arguments1, LogicalType::FLOAT, function1, nullptr);
    Value value_1(1.0F);
    std::shared_ptr<BoundConstantExpression> constant1_col = std::make_shared<BoundConstantExpression>(value_1);
    std::vector<std::shared_ptr<Expression>> expressions1 = {constant1_col, p1_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function1, expressions1, nullptr);
    discount_1_col->alias = "1-l_discount";

    std::vector<LogicalType> arguments2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p function2 = GetMulFunction();
    ScalarProjectFunction bound_function2("*", arguments2, LogicalType::FLOAT, function2, nullptr);
    std::vector<std::shared_ptr<Expression>> expressions2 = {p1_l_extendedprice, discount_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, bound_function2, expressions2, nullptr);
    extendedprice_discount_1_col->alias = "l_extendedprice*(1-l_discount)";

    Value value_0(0.0F);
    std::shared_ptr<BoundConstantExpression> p1_constant0_col = std::make_shared<BoundConstantExpression>(value_0);
    std::shared_ptr<BoundCaseExpression> case_expr1 = std::make_shared<BoundCaseExpression>();
    case_expr1->SetWhenExpr(functionExpression);
    case_expr1->SetThenExpr(extendedprice_discount_1_col);
    case_expr1->SetElseExpr(p1_constant0_col);
    case_expr1->alias = "case-1";

    std::vector<std::shared_ptr<Expression>> p1_expressions = {case_expr1, extendedprice_discount_1_col};
    // <case-1, l_extendedprice*(1-l_discount)>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建HashAgg================================================
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::SUM, AggFunctionType::SUM };
    std::vector<int32_t> group_item_idxs = { 0, 1 };
    // <Sum(case-1), Sum(l_extendedprice*(1-l_discount))>
    std::shared_ptr<PhysicalHashAgg> hashAgg1 = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, group_item_idxs);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p2_case_1 = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_sum_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 1, 0);
    std::vector<LogicalType> p2_arguments = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p p2_function = GetMulFunction();
    ScalarProjectFunction p2_bound_function("*", p2_arguments, LogicalType::DOUBLE, p2_function, nullptr);
    Value value_100d(100.0);
    std::shared_ptr<BoundConstantExpression> p2_constant100d_col = std::make_shared<BoundConstantExpression>(value_100d);
    std::vector<std::shared_ptr<Expression>> p2_expressions1 = {p2_constant100d_col, p2_case_1};
    std::shared_ptr<BoundProjectFunctionExpression> col_1 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::DOUBLE, p2_bound_function, p2_expressions1, nullptr);
    col_1->alias = "100.00*case_1";

    std::vector<LogicalType> p2_arguments2 = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p p2_function2 = GetDivFunction();
    ScalarProjectFunction p2_bound_function2("/", p2_arguments2, LogicalType::DOUBLE, p2_function2, nullptr);
    std::vector<std::shared_ptr<Expression>>p2_expressions2 = {col_1, p2_sum_2};
    std::shared_ptr<BoundProjectFunctionExpression> col_2 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::DOUBLE, p2_bound_function2, p2_expressions2, nullptr);
    col_2->alias = "promo_revenue";
    std::vector<std::shared_ptr<Expression>> p2_expressions3 = {col_2};
    // <promo_revenue>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions3);
    project2->exp_name = "2";
    std::shared_ptr<PhysicalResultCollector> result_collector = std::make_shared<PhysicalResultCollector>(project2);
    result_collector->AddChild(project2);
    project2->AddChild(hashAgg1);
    hashAgg1->AddChild(project1);
    project1->AddChild(join1);
    join1->AddChild(scan_part);
    join1->AddChild(filter1);
    filter1->AddChild(scan_lineitem);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    result_collector->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q14执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q15=============================
// 测试前需要先生成Revenue数据
// 测试单线程Q15查询
TEST(TPCHTest, Q15SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Revenue表数据
    std::shared_ptr<Table> table_revenue;
    InsertRevenue(table_revenue, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertRevenue Finish!!!", __FILE__, __LINE__);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    InsertSupplier(table_supplier, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> revenue_ids1 = {1};
    // <total_revenue>
    std::shared_ptr<PhysicalTableScan> scan_revenue1= std::make_shared<PhysicalTableScan>(table_revenue, -1, revenue_ids1);

    std::vector<int> revenue_ids2 = {0, 1};
    // <supplier_no, total_revenue>
    std::shared_ptr<PhysicalTableScan> scan_revenue2= std::make_shared<PhysicalTableScan>(table_revenue, -1, revenue_ids2);

    std::vector<int> supplier_ids = {0, 1, 2, 4};
    // <s_suppkey, s_name, s_address, s_phone>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    //  ================================================构建HashAgg================================================
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::MAX};
    std::vector<int32_t> group_item_idxs = {0};
    // <Max(total_revenue)>
    std::shared_ptr<PhysicalHashAgg> hashAgg1 = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, group_item_idxs);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {1};
    // <supplier_no, total_revenue, Max(total_revenue)>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join1->exp_name = "1";

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {0};
    // <supplier_no, total_revenue, Max(total_revenue), s_suppkey, s_name, s_address, s_phone>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join2->exp_name = "2";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_s_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_s_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 4, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_s_address = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_s_phone = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_total_revenue = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions1 = {p1_s_suppkey, p1_s_name, p1_s_address, p1_s_phone, p1_total_revenue};
    // < s_suppkey, s_name, s_address, s_phone, total_revenue>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions1);
    project1->exp_name = "1";
    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::INTEGER};
    std::vector<SortOrder> orders = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders);

    orderby->AddChild(project1);
    project1->AddChild(join2);
    join2->AddChild(scan_supplier);
    join2->AddChild(join1);
    join1->AddChild(hashAgg1);
    join1->AddChild(scan_revenue2);
    hashAgg1->AddChild(scan_revenue1);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q15执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q15查询
TEST(TPCHTest, Q15FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Revenue表数据
    std::shared_ptr<Table> table_revenue;
    std::vector<std::string> revenue_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "revenue.tbl_" + std::to_string(i);
        revenue_file_names.emplace_back(file_name);
    }
    InsertRevenueMul(table_revenue, scheduler, work_ids, partition_idxs, revenue_file_names);
    importFinish = false;
    spdlog::info("[{} : {}] InsertRevenue Finish!!!", __FILE__, __LINE__);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    std::vector<std::string> supplier_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "supplier.tbl_" + std::to_string(i);
        supplier_file_names.emplace_back(file_name);
    }
    InsertSupplierMul(table_supplier, scheduler, work_ids, partition_idxs, supplier_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> revenue_ids1 = {1};
    // <total_revenue>
    std::shared_ptr<PhysicalTableScan> scan_revenue1= std::make_shared<PhysicalTableScan>(table_revenue, -1, revenue_ids1);

    std::vector<int> revenue_ids2 = {0, 1};
    // <supplier_no, total_revenue>
    std::shared_ptr<PhysicalTableScan> scan_revenue2= std::make_shared<PhysicalTableScan>(table_revenue, -1, revenue_ids2);

    std::vector<int> supplier_ids = {0, 1, 2, 4};
    // <s_suppkey, s_name, s_address, s_phone>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    //  ================================================构建HashAgg================================================
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::MAX};
    std::vector<int32_t> group_item_idxs = {0};
    // <Max(total_revenue)>
    std::shared_ptr<PhysicalHashAgg> hashAgg1 = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, group_item_idxs);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {1};
    // <supplier_no, total_revenue, Max(total_revenue)>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join1->exp_name = "1";

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {0};
    // <supplier_no, total_revenue, Max(total_revenue), s_suppkey, s_name, s_address, s_phone>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join2->exp_name = "2";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_s_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_s_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 4, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_s_address = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_s_phone = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_total_revenue = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions1 = {p1_s_suppkey, p1_s_name, p1_s_address, p1_s_phone, p1_total_revenue};
    // < s_suppkey, s_name, s_address, s_phone, total_revenue>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions1);
    project1->exp_name = "1";
    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::INTEGER};
    std::vector<SortOrder> orders = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders);

    orderby->AddChild(project1);
    project1->AddChild(join2);
    join2->AddChild(scan_supplier);
    join2->AddChild(join1);
    join1->AddChild(hashAgg1);
    join1->AddChild(scan_revenue2);
    hashAgg1->AddChild(scan_revenue1);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q15执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q16=============================
// 测试单线程Q16查询
TEST(TPCHTest, Q16SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    InsertPart(table_part, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Partsupp表数据
    std::shared_ptr<Table> table_partsupp;
    InsertPartsupp(table_partsupp, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPartsupp Finish!!!", __FILE__, __LINE__);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    InsertSupplier(table_supplier, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> part_ids = {0, 3, 4, 5};
    // <p_partkey, p_brand, p_type, p_size>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    std::vector<int> partsupp_ids = {0, 1};
    // <ps_partkey, ps_suppkey>
    std::shared_ptr<PhysicalTableScan> scan_partsupp = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);

    std::vector<int> supplier_ids = {0, 6};
    // <s_suppkey, s_comment>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> p1_p_brand = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_p_type = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_p_size = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_Brand_45("Brand#45");
    std::shared_ptr<BoundConstantExpression> right_p_brand = std::make_shared<BoundConstantExpression>(value_Brand_45);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_NOTEQUAL, p1_p_brand, right_p_brand);

    std::string like_pattern = "MEDIUM POLISHED%";
    ScalarFunction bound_function = NotLikeFun::GetNotLikeFunction();
    Value value_pattern(like_pattern);
    std::shared_ptr<BoundConstantExpression> right_p_type = std::make_shared<BoundConstantExpression>(value_pattern);
    std::vector<std::shared_ptr<Expression>> arguments;
    arguments.push_back(std::move(p1_p_type));
    arguments.push_back(std::move(right_p_type));
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments, nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);

    std::vector<Value> value_set = {Value(49), Value(14), Value(23), Value(45), Value(19), Value(3), Value(36), Value(9)};
    std::shared_ptr<BoundInExpression> inExpression = std::make_shared<BoundInExpression>(p1_p_size, value_set, LogicalType::INTEGER);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression1 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression, functionExpression);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, conjunctionExpression1, inExpression);
    // <p_partkey, p_brand, p_type, p_size>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(conjunctionExpression2);

    std::shared_ptr<BoundColumnRefExpression> p2_s_comment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::string like_pattern2 = "%Customer%Complaints%";
    ScalarFunction bound_function2 = LikeFun::GetLikeFunction();
    Value value_pattern2(like_pattern2);
    std::shared_ptr<BoundConstantExpression> right_s_comment = std::make_shared<BoundConstantExpression>(value_pattern2);
    std::vector<std::shared_ptr<Expression>> arguments2;
    arguments2.push_back(std::move(p2_s_comment));
    arguments2.push_back(std::move(right_s_comment));
    std::shared_ptr<BoundFunctionExpression> functionExpression2 = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function2, arguments2, nullptr);
    functionExpression2->bind_info = functionExpression2->function.bind(functionExpression2->function, functionExpression2->children);
    // <s_suppkey, s_comment>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(functionExpression2);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {0};
    // <ps_partkey, ps_suppkey, p_partkey, p_brand, p_type, p_size>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join1->exp_name = "1";

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {1};
    // <ps_partkey, ps_suppkey, p_partkey, p_brand, p_type, p_size>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::ANTI, build_ids2, prode_ids2);
    join2->exp_name = "2";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p_brand = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> p_type = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 4, 0);
    std::shared_ptr<BoundColumnRefExpression> p_size = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> ps_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p_expressions = {p_brand, p_type, p_size, ps_suppkey};
    // < p_brand, p_type, p_size, ps_suppkey>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p_expressions);
    project1->exp_name = "1";

    // 构建HashAgg
    std::vector<int> group_set = {0, 1, 2};
    std::vector<int> agg_set = {3};
    std::vector<int> star_bitmap = {1};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::COUNT};
    // <p_brand, p_type, p_size, Count(ps_suppkey)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {3, 0, 1, 2};
    std::vector<LogicalType> key_types = {LogicalType::INTEGER, LogicalType::STRING, LogicalType::STRING, LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING, SortOrder::ASCENDING, SortOrder::ASCENDING, SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project1);
    project1->AddChild(join2);
    join2->AddChild(filter2);
    join2->AddChild(join1);
    filter2->AddChild(scan_supplier);
    join1->AddChild(filter1);
    join1->AddChild(scan_partsupp);
    filter1->AddChild(scan_part);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q16执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q16查询
TEST(TPCHTest, Q16FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    std::vector<std::string> part_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "part.tbl_" + std::to_string(i);
        part_file_names.emplace_back(file_name);
    }
    InsertPartMul(table_part, scheduler, work_ids, partition_idxs, part_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Partsupp表数据
    std::shared_ptr<Table> table_partsupp;
    std::vector<std::string> partsupp_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "partsupp.tbl_" + std::to_string(i);
        partsupp_file_names.emplace_back(file_name);
    }
    InsertPartsuppMul(table_partsupp, scheduler, work_ids, partition_idxs, partsupp_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertPartsupp Finish!!!", __FILE__, __LINE__);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    std::vector<std::string> supplier_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "supplier.tbl_" + std::to_string(i);
        supplier_file_names.emplace_back(file_name);
    }
    InsertSupplierMul(table_supplier, scheduler, work_ids, partition_idxs, supplier_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> part_ids = {0, 3, 4, 5};
    // <p_partkey, p_brand, p_type, p_size>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    std::vector<int> partsupp_ids = {0, 1};
    // <ps_partkey, ps_suppkey>
    std::shared_ptr<PhysicalTableScan> scan_partsupp = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);

    std::vector<int> supplier_ids = {0, 6};
    // <s_suppkey, s_comment>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> p1_p_brand = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_p_type = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_p_size = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_Brand_45("Brand#45");
    std::shared_ptr<BoundConstantExpression> right_p_brand = std::make_shared<BoundConstantExpression>(value_Brand_45);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_NOTEQUAL, p1_p_brand, right_p_brand);

    std::string like_pattern = "MEDIUM POLISHED%";
    ScalarFunction bound_function = NotLikeFun::GetNotLikeFunction();
    Value value_pattern(like_pattern);
    std::shared_ptr<BoundConstantExpression> right_p_type = std::make_shared<BoundConstantExpression>(value_pattern);
    std::vector<std::shared_ptr<Expression>> arguments;
    arguments.push_back(std::move(p1_p_type));
    arguments.push_back(std::move(right_p_type));
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments, nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);

    std::vector<Value> value_set = {Value(49), Value(14), Value(23), Value(45), Value(19), Value(3), Value(36), Value(9)};
    std::shared_ptr<BoundInExpression> inExpression = std::make_shared<BoundInExpression>(p1_p_size, value_set, LogicalType::INTEGER);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression1 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression, functionExpression);
    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, conjunctionExpression1, inExpression);
    // <p_partkey, p_brand, p_type, p_size>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(conjunctionExpression2);

    std::shared_ptr<BoundColumnRefExpression> p2_s_comment = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::string like_pattern2 = "%Customer%Complaints%";
    ScalarFunction bound_function2 = LikeFun::GetLikeFunction();
    Value value_pattern2(like_pattern2);
    std::shared_ptr<BoundConstantExpression> right_s_comment = std::make_shared<BoundConstantExpression>(value_pattern2);
    std::vector<std::shared_ptr<Expression>> arguments2;
    arguments2.push_back(std::move(p2_s_comment));
    arguments2.push_back(std::move(right_s_comment));
    std::shared_ptr<BoundFunctionExpression> functionExpression2 = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function2, arguments2, nullptr);
    functionExpression2->bind_info = functionExpression2->function.bind(functionExpression2->function, functionExpression2->children);
    // <s_suppkey, s_comment>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(functionExpression2);

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {0};
    // <ps_partkey, ps_suppkey, p_partkey, p_brand, p_type, p_size>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join1->exp_name = "1";

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {1};
    // <ps_partkey, ps_suppkey, p_partkey, p_brand, p_type, p_size>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::ANTI, build_ids2, prode_ids2);
    join2->exp_name = "2";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p_brand = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> p_type = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 4, 0);
    std::shared_ptr<BoundColumnRefExpression> p_size = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> ps_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p_expressions = {p_brand, p_type, p_size, ps_suppkey};
    // < p_brand, p_type, p_size, ps_suppkey>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p_expressions);
    project1->exp_name = "1";

    // 构建HashAgg
    std::vector<int> group_set = {0, 1, 2};
    std::vector<int> agg_set = {3};
    std::vector<int> star_bitmap = {1};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::COUNT};
    // <p_brand, p_type, p_size, Count(ps_suppkey)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {3, 0, 1, 2};
    std::vector<LogicalType> key_types = {LogicalType::INTEGER, LogicalType::STRING, LogicalType::STRING, LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING, SortOrder::ASCENDING, SortOrder::ASCENDING, SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg);
    hashAgg->AddChild(project1);
    project1->AddChild(join2);
    join2->AddChild(filter2);
    join2->AddChild(join1);
    filter2->AddChild(scan_supplier);
    join1->AddChild(filter1);
    join1->AddChild(scan_partsupp);
    filter1->AddChild(scan_part);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q16执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q17=============================
// 测试单线程Q17查询
TEST(TPCHTest, Q17SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    InsertPart(table_part, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> part_ids = {0, 3, 6};
    // <p_partkey, p_brand, p_container>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    std::vector<int> lineitem_ids1 = {1, 4};
    // <l_partkey, l_quantity>
    std::shared_ptr<PhysicalTableScan> scan_lineitem1 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids1);

    std::vector<int> lineitem_ids2 = {1, 4, 5};
    // <l_partkey, l_quantity, l_extendedprice>
    std::shared_ptr<PhysicalTableScan> scan_lineitem2 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids2);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> p1_p_brand = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_p_container = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);

    Value value_Brand_23("Brand#23");
    std::shared_ptr<BoundConstantExpression> right_p_brand = std::make_shared<BoundConstantExpression>(value_Brand_23);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, p1_p_brand, right_p_brand);

    Value value_MED("MED BOX");
    std::shared_ptr<BoundConstantExpression> right_p_container = std::make_shared<BoundConstantExpression>(value_MED);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, p1_p_container, right_p_container);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression, comparisonExpression2);
    // <p_partkey, p_brand, p_container>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(conjunctionExpression);
    filter1->exp_name = "1";
    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {0};
    // <l_partkey, l_quantity, l_extendedprice, p_partkey, p_brand, p_container>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join1->exp_name = "1";

    // 构建HashAgg
    std::vector<int> group_set1 = {0};
    std::vector<int> agg_set1 = {1};
    std::vector<int> star_bitmap1 = {0};
    std::vector<AggFunctionType> aggregate_function_types1 = {AggFunctionType::AVG};
    // <l_partkey, Avg(l_quantity)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg1 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set1, agg_set1, star_bitmap1, aggregate_function_types1);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> l_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 1, 0);
    std::vector<LogicalType> p1_arguments = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p p1_function = GetMulFunction();
    ScalarProjectFunction p1_bound_function("*", p1_arguments, LogicalType::DOUBLE, p1_function, nullptr);
    Value value_2d(0.2);
    std::shared_ptr<BoundConstantExpression> p1_constant = std::make_shared<BoundConstantExpression>(value_2d);
    std::vector<std::shared_ptr<Expression>> p1_expressions1 = {p1_constant, l_quantity};
    std::shared_ptr<BoundProjectFunctionExpression> l_quantity_0_2 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::DOUBLE, p1_bound_function, p1_expressions1, nullptr);
    l_quantity_0_2->alias = "0.2 * avg(l_quantity)";
    std::vector<std::shared_ptr<Expression>> p1_expressions = {l_partkey, l_quantity_0_2};
    // <l_partkey, 0.2 * avg(l_quantity)>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {3};
    // <l_partkey, l_quantity, l_extendedprice, p_partkey, p_brand, p_container, l_partkey, 0.2 * avg(l_quantity)>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join2->exp_name = "2";

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f2_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> f2_avg_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 7, 0);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN, f2_l_quantity, f2_avg_l_quantity);
    // <l_partkey, l_quantity, l_extendedprice, p_partkey, p_brand, p_container, l_partkey, 0.2 * avg(l_quantity)>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(f2_comparisonExpression);
    filter2->exp_name = "2";
    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p2_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);;
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_l_extendedprice};
    // <l_extendedprice>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";
    // 构建HashAgg
    std::vector<AggFunctionType> aggregate_function_types2 = { AggFunctionType::SUM};
    std::vector<int32_t> group_item_idxs2 = {0};
    // <Sum(l_extendedprice)>
    std::shared_ptr<PhysicalHashAgg> hashAgg2 = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types2, group_item_idxs2);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p3_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 0, 0);;
    std::vector<LogicalType> p3_arguments = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p p3_function = GetDivFunction();
    ScalarProjectFunction p3_bound_function("/", p3_arguments, LogicalType::DOUBLE, p3_function, nullptr);
    Value value_7d(7.0);
    std::shared_ptr<BoundConstantExpression> p3_constant = std::make_shared<BoundConstantExpression>(value_7d);
    std::vector<std::shared_ptr<Expression>> p3_expressions1 = {p3_l_extendedprice, p3_constant};
    std::shared_ptr<BoundProjectFunctionExpression> l_extendedprice_3 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::DOUBLE, p3_bound_function, p3_expressions1, nullptr);
    l_extendedprice_3->alias = "Sum(l_extendedprice) / 7.0";
    std::vector<std::shared_ptr<Expression>> p3_expressions = {l_extendedprice_3};
    // <Sum(l_extendedprice) / 7.0>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions);
    project3->exp_name = "3";
    std::shared_ptr<PhysicalResultCollector> result_collector = std::make_shared<PhysicalResultCollector>(project3);

    result_collector->AddChild(project3);
    project3->AddChild(hashAgg2);
    hashAgg2->AddChild(project2);
    project2->AddChild(filter2);
    filter2->AddChild(join2);
    join2->AddChild(project1);
    join2->AddChild(join1);
    project1->AddChild(hashAgg1);
    hashAgg1->AddChild(scan_lineitem1);
    join1->AddChild(filter1);
    join1->AddChild(scan_lineitem2);
    filter1->AddChild(scan_part);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    result_collector->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q17执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q17查询
TEST(TPCHTest, Q17FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    std::vector<std::string> part_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "part.tbl_" + std::to_string(i);
        part_file_names.emplace_back(file_name);
    }
    InsertPartMul(table_part, scheduler, work_ids, partition_idxs, part_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> part_ids = {0, 3, 6};
    // <p_partkey, p_brand, p_container>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    std::vector<int> lineitem_ids1 = {1, 4};
    // <l_partkey, l_quantity>
    std::shared_ptr<PhysicalTableScan> scan_lineitem1 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids1);

    std::vector<int> lineitem_ids2 = {1, 4, 5};
    // <l_partkey, l_quantity, l_extendedprice>
    std::shared_ptr<PhysicalTableScan> scan_lineitem2 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids2);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> p1_p_brand = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_p_container = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);

    Value value_Brand_23("Brand#23");
    std::shared_ptr<BoundConstantExpression> right_p_brand = std::make_shared<BoundConstantExpression>(value_Brand_23);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, p1_p_brand, right_p_brand);

    Value value_MED("MED BOX");
    std::shared_ptr<BoundConstantExpression> right_p_container = std::make_shared<BoundConstantExpression>(value_MED);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, p1_p_container, right_p_container);

    std::shared_ptr<BoundConjunctionExpression> conjunctionExpression = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, comparisonExpression, comparisonExpression2);
    // <p_partkey, p_brand, p_container>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(conjunctionExpression);
    filter1->exp_name = "1";
    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {0};
    // <l_partkey, l_quantity, l_extendedprice, p_partkey, p_brand, p_container>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids1, prode_ids1);
    join1->exp_name = "1";

    // 构建HashAgg
    std::vector<int> group_set1 = {0};
    std::vector<int> agg_set1 = {1};
    std::vector<int> star_bitmap1 = {0};
    std::vector<AggFunctionType> aggregate_function_types1 = {AggFunctionType::AVG};
    // <l_partkey, Avg(l_quantity)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg1 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set1, agg_set1, star_bitmap1, aggregate_function_types1);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> l_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 1, 0);
    std::vector<LogicalType> p1_arguments = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p p1_function = GetMulFunction();
    ScalarProjectFunction p1_bound_function("*", p1_arguments, LogicalType::DOUBLE, p1_function, nullptr);
    Value value_2d(0.2);
    std::shared_ptr<BoundConstantExpression> p1_constant = std::make_shared<BoundConstantExpression>(value_2d);
    std::vector<std::shared_ptr<Expression>> p1_expressions1 = {p1_constant, l_quantity};
    std::shared_ptr<BoundProjectFunctionExpression> l_quantity_0_2 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::DOUBLE, p1_bound_function, p1_expressions1, nullptr);
    l_quantity_0_2->alias = "0.2 * avg(l_quantity)";
    std::vector<std::shared_ptr<Expression>> p1_expressions = {l_partkey, l_quantity_0_2};
    // <l_partkey, 0.2 * avg(l_quantity)>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {3};
    // <l_partkey, l_quantity, l_extendedprice, p_partkey, p_brand, p_container, l_partkey, 0.2 * avg(l_quantity)>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join2->exp_name = "2";

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f2_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> f2_avg_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 7, 0);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN, f2_l_quantity, f2_avg_l_quantity);
    // <l_partkey, l_quantity, l_extendedprice, p_partkey, p_brand, p_container, l_partkey, 0.2 * avg(l_quantity)>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(f2_comparisonExpression);
    filter2->exp_name = "2";
    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p2_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);;
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_l_extendedprice};
    // <l_extendedprice>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";
    // 构建HashAgg
    std::vector<AggFunctionType> aggregate_function_types2 = { AggFunctionType::SUM};
    std::vector<int32_t> group_item_idxs2 = {0};
    // <Sum(l_extendedprice)>
    std::shared_ptr<PhysicalHashAgg> hashAgg2 = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types2, group_item_idxs2);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p3_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 0, 0);;
    std::vector<LogicalType> p3_arguments = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p p3_function = GetDivFunction();
    ScalarProjectFunction p3_bound_function("/", p3_arguments, LogicalType::DOUBLE, p3_function, nullptr);
    Value value_7d(7.0);
    std::shared_ptr<BoundConstantExpression> p3_constant = std::make_shared<BoundConstantExpression>(value_7d);
    std::vector<std::shared_ptr<Expression>> p3_expressions1 = {p3_l_extendedprice, p3_constant};
    std::shared_ptr<BoundProjectFunctionExpression> l_extendedprice_3 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::DOUBLE, p3_bound_function, p3_expressions1, nullptr);
    l_extendedprice_3->alias = "Sum(l_extendedprice) / 7.0";
    std::vector<std::shared_ptr<Expression>> p3_expressions = {l_extendedprice_3};
    // <Sum(l_extendedprice) / 7.0>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions);
    project3->exp_name = "3";
    std::shared_ptr<PhysicalResultCollector> result_collector = std::make_shared<PhysicalResultCollector>(project3);

    result_collector->AddChild(project3);
    project3->AddChild(hashAgg2);
    hashAgg2->AddChild(project2);
    project2->AddChild(filter2);
    filter2->AddChild(join2);
    join2->AddChild(project1);
    join2->AddChild(join1);
    project1->AddChild(hashAgg1);
    hashAgg1->AddChild(scan_lineitem1);
    join1->AddChild(filter1);
    join1->AddChild(scan_lineitem2);
    filter1->AddChild(scan_part);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    result_collector->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q17执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q18=============================
// 测试单线程Q18查询
TEST(TPCHTest, Q18SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    InsertCustomer(table_customer, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    InsertOrders(table_orders, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> lineitem_ids1 = {0, 4};
    // <l_orderkey, l_quantity>
    std::shared_ptr<PhysicalTableScan> scan_lineitem1 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids1);

    std::vector<int> lineitem_ids2 = {0, 4};
    // <l_orderkey, l_quantity>
    std::shared_ptr<PhysicalTableScan> scan_lineitem2 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids2);

    std::vector<int> customer_ids = {0, 1};
    // <c_custkey, c_name>
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> orders_ids = {0, 1, 3, 4};
    // <o_orderkey, o_custkey, o_totalprice, o_orderdate>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    // ================================================构建HashAgg================================================
    std::vector<int> group_set = {0};
    std::vector<int> agg_set = {1};
    std::vector<int> star_bitmap = {0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM};
    // <l_orderkey, Sum(l_quantity)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg1 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_sum_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 1, 0);

    Value value_300(300.0);
    std::shared_ptr<BoundConstantExpression> right_sum_l_quantity = std::make_shared<BoundConstantExpression>(value_300);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHAN, f1_sum_l_quantity, right_sum_l_quantity);
    // <l_orderkey, Sum(l_quantity)>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(comparisonExpression);
    filter1->exp_name = "1";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_l_orderkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_l_orderkey};
    // <l_orderkey>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f2_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    Value value_14999(14999);
    std::shared_ptr<BoundConstantExpression> right_c_custkey = std::make_shared<BoundConstantExpression>(value_14999);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f2_c_custkey, right_c_custkey);
    // <c_custkey, c_name>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(f2_comparisonExpression);
    filter2->exp_name = "2";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids3 = {0};
    std::vector<int> prode_ids3 = {1};
    // <o_orderkey, o_custkey, o_totalprice, o_orderdate, c_custkey, c_name>
    std::shared_ptr<PhysicalHashJoin> join3 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    join3->exp_name = "3";

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {0};
    // <l_orderkey, l_quantity, o_orderkey, o_custkey, o_totalprice, o_orderdate, c_custkey, c_name>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join2->exp_name = "2";

    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {2};
    // <l_orderkey, l_quantity, o_orderkey, o_custkey, o_totalprice, o_orderdate, c_custkey, c_name>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::SEMI, build_ids1, prode_ids1);
    join1->exp_name = "1";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p2_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_o_orderkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_o_totalprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 4, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 7, 0);
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_l_quantity, p2_o_orderkey, p2_o_totalprice, p2_o_orderdate, p2_c_custkey, p2_c_name};
    // <l_quantity, o_orderkey, o_totalprice, o_orderdate, c_custkey, c_name>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    // 构建HashAgg
    std::vector<int> group_set2 = {5, 4, 1, 3, 2};
    std::vector<int> agg_set2 = {0};
    std::vector<int> star_bitmap2 = {0};
    std::vector<AggFunctionType> aggregate_function_types2 = {AggFunctionType::SUM};
    // <c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice, Sum(l_quantity)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg2 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set2, agg_set2, star_bitmap2, aggregate_function_types2);

    // 构建OrderBy
    std::vector<int> sort_keys = {4, 3};
    std::vector<LogicalType> key_types = {LogicalType::FLOAT, LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING, SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg2);
    hashAgg2->AddChild(project2);
    project2->AddChild(join1);
    join1->AddChild(project1);
    join1->AddChild(join2);
    project1->AddChild(filter1);
    filter1->AddChild(hashAgg1);
    hashAgg1->AddChild(scan_lineitem1);
    join2->AddChild(join3);
    join2->AddChild(scan_lineitem2);
    join3->AddChild(filter2);
    join3->AddChild(scan_orders);
    filter2->AddChild(scan_customer);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q18执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q18查询
TEST(TPCHTest, Q18FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    std::vector<std::string> customer_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "customer.tbl_" + std::to_string(i);
        customer_file_names.emplace_back(file_name);
    }
    InsertCustomerMul(table_customer, scheduler, work_ids, partition_idxs, customer_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> lineitem_ids1 = {0, 4};
    // <l_orderkey, l_quantity>
    std::shared_ptr<PhysicalTableScan> scan_lineitem1 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids1);

    std::vector<int> lineitem_ids2 = {0, 4};
    // <l_orderkey, l_quantity>
    std::shared_ptr<PhysicalTableScan> scan_lineitem2 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids2);

    std::vector<int> customer_ids = {0, 1};
    // <c_custkey, c_name>
    std::shared_ptr<PhysicalTableScan> scan_customer = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> orders_ids = {0, 1, 3, 4};
    // <o_orderkey, o_custkey, o_totalprice, o_orderdate>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    // ================================================构建HashAgg================================================
    std::vector<int> group_set = {0};
    std::vector<int> agg_set = {1};
    std::vector<int> star_bitmap = {0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM};
    // <l_orderkey, Sum(l_quantity)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg1 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_sum_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 1, 0);

    Value value_300(300.0);
    std::shared_ptr<BoundConstantExpression> right_sum_l_quantity = std::make_shared<BoundConstantExpression>(value_300);
    std::shared_ptr<BoundComparisonExpression> comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHAN, f1_sum_l_quantity, right_sum_l_quantity);
    // <l_orderkey, Sum(l_quantity)>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(comparisonExpression);
    filter1->exp_name = "1";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_l_orderkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_l_orderkey};
    // <l_orderkey>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f2_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    Value value_14999(14999);
    std::shared_ptr<BoundConstantExpression> right_c_custkey = std::make_shared<BoundConstantExpression>(value_14999);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f2_c_custkey, right_c_custkey);
    // <c_custkey, c_name>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(f2_comparisonExpression);
    filter2->exp_name = "2";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids3 = {0};
    std::vector<int> prode_ids3 = {1};
    // <o_orderkey, o_custkey, o_totalprice, o_orderdate, c_custkey, c_name>
    std::shared_ptr<PhysicalHashJoin> join3 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    join3->exp_name = "3";

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {0};
    // <l_orderkey, l_quantity, o_orderkey, o_custkey, o_totalprice, o_orderdate, c_custkey, c_name>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join2->exp_name = "2";

    std::vector<int> build_ids1 = {0};
    std::vector<int> prode_ids1 = {2};
    // <l_orderkey, l_quantity, o_orderkey, o_custkey, o_totalprice, o_orderdate, c_custkey, c_name>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::SEMI, build_ids1, prode_ids1);
    join1->exp_name = "1";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p2_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_o_orderkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_o_totalprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 4, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_o_orderdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 5, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_c_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 7, 0);
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_l_quantity, p2_o_orderkey, p2_o_totalprice, p2_o_orderdate, p2_c_custkey, p2_c_name};
    // <l_quantity, o_orderkey, o_totalprice, o_orderdate, c_custkey, c_name>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    // 构建HashAgg
    std::vector<int> group_set2 = {5, 4, 1, 3, 2};
    std::vector<int> agg_set2 = {0};
    std::vector<int> star_bitmap2 = {0};
    std::vector<AggFunctionType> aggregate_function_types2 = {AggFunctionType::SUM};
    // <c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice, Sum(l_quantity)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg2 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set2, agg_set2, star_bitmap2, aggregate_function_types2);

    // 构建OrderBy
    std::vector<int> sort_keys = {4, 3};
    std::vector<LogicalType> key_types = {LogicalType::FLOAT, LogicalType::INTEGER};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING, SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg2);
    hashAgg2->AddChild(project2);
    project2->AddChild(join1);
    join1->AddChild(project1);
    join1->AddChild(join2);
    project1->AddChild(filter1);
    filter1->AddChild(hashAgg1);
    hashAgg1->AddChild(scan_lineitem1);
    join2->AddChild(join3);
    join2->AddChild(scan_lineitem2);
    join3->AddChild(filter2);
    join3->AddChild(scan_orders);
    filter2->AddChild(scan_customer);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q18执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q19=============================
// 测试单线程Q19查询
TEST(TPCHTest, Q19SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    InsertPart(table_part, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> lineitem_ids = {1,4,5,6,13,14};
    // <l_partkey, l_quantity, l_extendedprice, l_discount, l_shipinstruct, l_shipmode>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> part_ids = {0,3,5,6};
    // <p_partkey, p_brand, p_size, p_container>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_l_shipinstruct = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 4, 0);
    Value value_1("DELIVER IN PERSON");
    std::shared_ptr<BoundConstantExpression> right_l_shipinstruct = std::make_shared<BoundConstantExpression>(value_1);
    std::shared_ptr<BoundComparisonExpression> f1_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f1_l_shipinstruct, right_l_shipinstruct);
    // <l_partkey, l_quantity, l_extendedprice, l_discount, l_shipinstruct, l_shipmode>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(f1_comparisonExpression);
    filter1->exp_name = "1";

    std::shared_ptr<BoundColumnRefExpression> f2_l_shipmode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    Value value_2("AIR");
    std::shared_ptr<BoundConstantExpression> right_l_shipmode = std::make_shared<BoundConstantExpression>(value_2);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f2_l_shipmode, right_l_shipmode);
    std::shared_ptr<BoundColumnRefExpression> f2_l_shipmode2 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    Value value_3("AIR REG");
    std::shared_ptr<BoundConstantExpression> right_l_shipmode2 = std::make_shared<BoundConstantExpression>(value_3);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f2_l_shipmode2, right_l_shipmode2);
    std::shared_ptr<BoundConjunctionExpression> f2_conjunctionExpression = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_OR, f2_comparisonExpression, f2_comparisonExpression2);
    // <l_partkey, l_quantity, l_extendedprice, l_discount, l_shipinstruct, l_shipmode>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(f2_conjunctionExpression);
    filter2->exp_name = "2";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_l_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 3, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_l_partkey,p1_l_quantity,p1_l_extendedprice,p1_l_discount};
    // <l_partkey, l_quantity, l_extendedprice, l_discount>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids = {0};
    std::vector<int> prode_ids = {0};
    // <l_partkey, l_quantity, l_extendedprice, l_discount, p_partkey, p_brand, p_size, p_container>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids, prode_ids);
    join1->exp_name = "1";

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f3_p_brand1 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    Value value_Brand_12("Brand#12");
    std::shared_ptr<BoundConstantExpression> right_p_brand1 = std::make_shared<BoundConstantExpression>(value_Brand_12);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression1 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f3_p_brand1, right_p_brand1);

    std::shared_ptr<BoundColumnRefExpression> f3_l_quantity1 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value value_1f(1.0f);
    std::shared_ptr<BoundConstantExpression> right_l_quantity1 = std::make_shared<BoundConstantExpression>(value_1f);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f3_l_quantity1, right_l_quantity1);

    std::shared_ptr<BoundColumnRefExpression> f3_l_quantity2 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value value_11f(11.0f);
    std::shared_ptr<BoundConstantExpression> right_l_quantity2 = std::make_shared<BoundConstantExpression>(value_11f);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f3_l_quantity2, right_l_quantity2);

    std::shared_ptr<BoundColumnRefExpression> f3_p_size1 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    Value value_1l(1);
    std::shared_ptr<BoundConstantExpression> right_p_size1 = std::make_shared<BoundConstantExpression>(value_1l);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression4 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f3_p_size1, right_p_size1);

    std::shared_ptr<BoundColumnRefExpression> f3_p_size2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    Value value_5l(5);
    std::shared_ptr<BoundConstantExpression> right_p_size2 = std::make_shared<BoundConstantExpression>(value_5l);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression5 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f3_p_size2, right_p_size2);

    Value value_SM1("SM CASE");
    Value value_SM2("SM BOX");
    Value value_SM3("SM PACK");
    Value value_SM4("SM PKG");
    std::vector<Value> value_SM_set = {value_SM1, value_SM2, value_SM3, value_SM4};
    std::shared_ptr<BoundColumnRefExpression> f3_p_container = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 7, 0);
    std::shared_ptr<BoundInExpression> f3_inExpression1 = std::make_shared<BoundInExpression>(f3_p_container, value_SM_set, LogicalType::STRING);

    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression1 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression2, f3_comparisonExpression3);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression4, f3_comparisonExpression5);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_conjunctionExpression1, f3_conjunctionExpression2);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression4 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_conjunctionExpression3, f3_inExpression1);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression5 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression1, f3_conjunctionExpression4);
    f3_conjunctionExpression5->alias = "1";
    std::shared_ptr<BoundColumnRefExpression> f3_p_brand1_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    Value value_Brand_23("Brand#23");
    std::shared_ptr<BoundConstantExpression> right_p_brand1_2 = std::make_shared<BoundConstantExpression>(value_Brand_23);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression1_2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f3_p_brand1_2, right_p_brand1_2);

    std::shared_ptr<BoundColumnRefExpression> f3_l_quantity1_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value value_10f(10.0f);
    std::shared_ptr<BoundConstantExpression> right_l_quantity1_2 = std::make_shared<BoundConstantExpression>(value_10f);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression2_2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f3_l_quantity1_2, right_l_quantity1_2);

    std::shared_ptr<BoundColumnRefExpression> f3_l_quantity2_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value value_20f(20.0f);
    std::shared_ptr<BoundConstantExpression> right_l_quantity2_2 = std::make_shared<BoundConstantExpression>(value_20f);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression3_2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f3_l_quantity2_2, right_l_quantity2_2);

    std::shared_ptr<BoundColumnRefExpression> f3_p_size1_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    std::shared_ptr<BoundConstantExpression> right_p_size1_2 = std::make_shared<BoundConstantExpression>(value_1l);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression4_2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f3_p_size1_2, right_p_size1_2);

    std::shared_ptr<BoundColumnRefExpression> f3_p_size2_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    Value value_10l(10);
    std::shared_ptr<BoundConstantExpression> right_p_size2_2 = std::make_shared<BoundConstantExpression>(value_10l);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression5_2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f3_p_size2_2, right_p_size2_2);

    Value value_MED1("MED BAG");
    Value value_MED2("MED BOX");
    Value value_MED3("MED PACK");
    Value value_MED4("MED PKG");
    std::vector<Value> value_MED_set = {value_MED1, value_MED2, value_MED3, value_MED4};
    std::shared_ptr<BoundColumnRefExpression> f3_p_container_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 7, 0);
    std::shared_ptr<BoundInExpression> f3_inExpression1_2 = std::make_shared<BoundInExpression>(f3_p_container_2, value_MED_set, LogicalType::STRING);

    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression1_2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression2_2, f3_comparisonExpression3_2);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression2_2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression4_2, f3_comparisonExpression5_2);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression3_2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_conjunctionExpression1_2, f3_conjunctionExpression2_2);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression4_2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_conjunctionExpression3_2, f3_inExpression1_2);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression5_2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression1_2, f3_conjunctionExpression4_2);
    f3_conjunctionExpression5_2->alias = "2";
    std::shared_ptr<BoundColumnRefExpression> f3_p_brand1_3 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    Value value_Brand_34("Brand#34");
    std::shared_ptr<BoundConstantExpression> right_p_brand1_3 = std::make_shared<BoundConstantExpression>(value_Brand_34);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression1_3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f3_p_brand1_3, right_p_brand1_3);

    std::shared_ptr<BoundColumnRefExpression> f3_l_quantity1_3 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    std::shared_ptr<BoundConstantExpression> right_l_quantity1_3 = std::make_shared<BoundConstantExpression>(value_20f);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression2_3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f3_l_quantity1_3, right_l_quantity1_3);

    std::shared_ptr<BoundColumnRefExpression> f3_l_quantity2_3 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value value_30f(30.0f);
    std::shared_ptr<BoundConstantExpression> right_l_quantity2_3 = std::make_shared<BoundConstantExpression>(value_30f);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression3_3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f3_l_quantity2_3, right_l_quantity2_3);

    std::shared_ptr<BoundColumnRefExpression> f3_p_size1_3 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    std::shared_ptr<BoundConstantExpression> right_p_size1_3 = std::make_shared<BoundConstantExpression>(value_1l);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression4_3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f3_p_size1_3, right_p_size1_3);

    std::shared_ptr<BoundColumnRefExpression> f3_p_size2_3 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    Value value_15l(15);
    std::shared_ptr<BoundConstantExpression> right_p_size2_3 = std::make_shared<BoundConstantExpression>(value_15l);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression5_3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f3_p_size2_3, right_p_size2_3);

    Value value_LG1("LG CASE");
    Value value_LG2("LG BOX");
    Value value_LG3("LG PACK");
    Value value_LG4("LG PKG");
    std::vector<Value> value_LG_set = {value_LG1, value_LG2, value_LG3, value_LG4};
    std::shared_ptr<BoundColumnRefExpression> f3_p_container_3 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 7, 0);
    std::shared_ptr<BoundInExpression> f3_inExpression1_3 = std::make_shared<BoundInExpression>(f3_p_container_3, value_LG_set, LogicalType::STRING);

    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression1_3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression2_3, f3_comparisonExpression3_3);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression2_3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression4_3, f3_comparisonExpression5_3);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression3_3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_conjunctionExpression1_3, f3_conjunctionExpression2_3);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression4_3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_conjunctionExpression3_3, f3_inExpression1_3);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression5_3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression1_3, f3_conjunctionExpression4_3);
    f3_conjunctionExpression5_3->alias = "3";
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression6 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_OR, f3_conjunctionExpression5, f3_conjunctionExpression5_2);
    f3_conjunctionExpression6->alias = "4";
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression7 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_OR, f3_conjunctionExpression6, f3_conjunctionExpression5_3);
    f3_conjunctionExpression7->alias = "5";
    // <l_partkey, l_quantity, l_extendedprice, l_discount, p_partkey, p_brand, p_size, p_container>
    std::shared_ptr<PhysicalFilter> filter3 = std::make_shared<PhysicalFilter>(f3_conjunctionExpression7);
    // std::shared_ptr<PhysicalFilter> filter3 = std::make_shared<PhysicalFilter>(f3_conjunctionExpression5_3);
    filter3->exp_name = "3";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p2_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 3, 0);

    std::vector<LogicalType> p2_arguments1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p p2_function1 = GetSubFunction();
    ScalarProjectFunction p2_bound_function1("-", p2_arguments1, LogicalType::FLOAT, p2_function1, nullptr);
    std::shared_ptr<BoundConstantExpression> constant1_col = std::make_shared<BoundConstantExpression>(value_1f);
    std::vector<std::shared_ptr<Expression>> p2_expressions1 = {constant1_col, p2_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p2_bound_function1, p2_expressions1, nullptr);
    discount_1_col->alias = "1-l_discount";

    std::vector<LogicalType> p2_arguments2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p p2_function2 = GetMulFunction();
    ScalarProjectFunction p2_bound_function2("*", p2_arguments2, LogicalType::FLOAT, p2_function2, nullptr);
    std::vector<std::shared_ptr<Expression>> p2_expressions2 = {p2_l_extendedprice, discount_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p2_bound_function2, p2_expressions2, nullptr);
    extendedprice_discount_1_col->alias = "l_extendedprice * (1 - l_discount)";

    std::vector<std::shared_ptr<Expression>> p2_expressions = {extendedprice_discount_1_col};
    // <l_extendedprice * (1 - l_discount)>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    // ================================================构建HashAgg================================================
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::SUM};
    std::vector<int32_t> group_item_idxs = {0};
    // <Sum(l_extendedprice * (1 - l_discount))>
    std::shared_ptr<PhysicalHashAgg> hashAgg = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, group_item_idxs);


    hashAgg->AddChild(project2);
    project2->AddChild(filter3);
    filter3->AddChild(join1);
    join1->AddChild(scan_part);
    join1->AddChild(project1);
    project1->AddChild(filter2);
    filter2->AddChild(filter1);
    filter1->AddChild(scan_lineitem);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    hashAgg->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q19执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q19查询
TEST(TPCHTest, Q19FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    std::vector<std::string> part_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "part.tbl_" + std::to_string(i);
        part_file_names.emplace_back(file_name);
    }
    InsertPartMul(table_part, scheduler, work_ids, partition_idxs, part_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> lineitem_ids = {1,4,5,6,13,14};
    // <l_partkey, l_quantity, l_extendedprice, l_discount, l_shipinstruct, l_shipmode>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> part_ids = {0,3,5,6};
    // <p_partkey, p_brand, p_size, p_container>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_l_shipinstruct = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 4, 0);
    Value value_1("DELIVER IN PERSON");
    std::shared_ptr<BoundConstantExpression> right_l_shipinstruct = std::make_shared<BoundConstantExpression>(value_1);
    std::shared_ptr<BoundComparisonExpression> f1_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f1_l_shipinstruct, right_l_shipinstruct);
    // <l_partkey, l_quantity, l_extendedprice, l_discount, l_shipinstruct, l_shipmode>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(f1_comparisonExpression);
    filter1->exp_name = "1";

    std::shared_ptr<BoundColumnRefExpression> f2_l_shipmode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    Value value_2("AIR");
    std::shared_ptr<BoundConstantExpression> right_l_shipmode = std::make_shared<BoundConstantExpression>(value_2);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f2_l_shipmode, right_l_shipmode);
    std::shared_ptr<BoundColumnRefExpression> f2_l_shipmode2 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    Value value_3("AIR REG");
    std::shared_ptr<BoundConstantExpression> right_l_shipmode2 = std::make_shared<BoundConstantExpression>(value_3);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f2_l_shipmode2, right_l_shipmode2);
    std::shared_ptr<BoundConjunctionExpression> f2_conjunctionExpression = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_OR, f2_comparisonExpression, f2_comparisonExpression2);
    // <l_partkey, l_quantity, l_extendedprice, l_discount, l_shipinstruct, l_shipmode>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(f2_conjunctionExpression);
    filter2->exp_name = "2";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_l_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 3, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_l_partkey,p1_l_quantity,p1_l_extendedprice,p1_l_discount};
    // <l_partkey, l_quantity, l_extendedprice, l_discount>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids = {0};
    std::vector<int> prode_ids = {0};
    // <l_partkey, l_quantity, l_extendedprice, l_discount, p_partkey, p_brand, p_size, p_container>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids, prode_ids);
    join1->exp_name = "1";

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f3_p_brand1 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    Value value_Brand_12("Brand#12");
    std::shared_ptr<BoundConstantExpression> right_p_brand1 = std::make_shared<BoundConstantExpression>(value_Brand_12);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression1 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f3_p_brand1, right_p_brand1);

    std::shared_ptr<BoundColumnRefExpression> f3_l_quantity1 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value value_1f(1.0f);
    std::shared_ptr<BoundConstantExpression> right_l_quantity1 = std::make_shared<BoundConstantExpression>(value_1f);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f3_l_quantity1, right_l_quantity1);

    std::shared_ptr<BoundColumnRefExpression> f3_l_quantity2 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value value_11f(11.0f);
    std::shared_ptr<BoundConstantExpression> right_l_quantity2 = std::make_shared<BoundConstantExpression>(value_11f);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f3_l_quantity2, right_l_quantity2);

    std::shared_ptr<BoundColumnRefExpression> f3_p_size1 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    Value value_1l(1);
    std::shared_ptr<BoundConstantExpression> right_p_size1 = std::make_shared<BoundConstantExpression>(value_1l);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression4 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f3_p_size1, right_p_size1);

    std::shared_ptr<BoundColumnRefExpression> f3_p_size2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    Value value_5l(5);
    std::shared_ptr<BoundConstantExpression> right_p_size2 = std::make_shared<BoundConstantExpression>(value_5l);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression5 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f3_p_size2, right_p_size2);

    Value value_SM1("SM CASE");
    Value value_SM2("SM BOX");
    Value value_SM3("SM PACK");
    Value value_SM4("SM PKG");
    std::vector<Value> value_SM_set = {value_SM1, value_SM2, value_SM3, value_SM4};
    std::shared_ptr<BoundColumnRefExpression> f3_p_container = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 7, 0);
    std::shared_ptr<BoundInExpression> f3_inExpression1 = std::make_shared<BoundInExpression>(f3_p_container, value_SM_set, LogicalType::STRING);

    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression1 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression2, f3_comparisonExpression3);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression4, f3_comparisonExpression5);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_conjunctionExpression1, f3_conjunctionExpression2);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression4 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_conjunctionExpression3, f3_inExpression1);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression5 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression1, f3_conjunctionExpression4);
    f3_conjunctionExpression5->alias = "1";
    std::shared_ptr<BoundColumnRefExpression> f3_p_brand1_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    Value value_Brand_23("Brand#23");
    std::shared_ptr<BoundConstantExpression> right_p_brand1_2 = std::make_shared<BoundConstantExpression>(value_Brand_23);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression1_2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f3_p_brand1_2, right_p_brand1_2);

    std::shared_ptr<BoundColumnRefExpression> f3_l_quantity1_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value value_10f(10.0f);
    std::shared_ptr<BoundConstantExpression> right_l_quantity1_2 = std::make_shared<BoundConstantExpression>(value_10f);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression2_2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f3_l_quantity1_2, right_l_quantity1_2);

    std::shared_ptr<BoundColumnRefExpression> f3_l_quantity2_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value value_20f(20.0f);
    std::shared_ptr<BoundConstantExpression> right_l_quantity2_2 = std::make_shared<BoundConstantExpression>(value_20f);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression3_2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f3_l_quantity2_2, right_l_quantity2_2);

    std::shared_ptr<BoundColumnRefExpression> f3_p_size1_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    std::shared_ptr<BoundConstantExpression> right_p_size1_2 = std::make_shared<BoundConstantExpression>(value_1l);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression4_2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f3_p_size1_2, right_p_size1_2);

    std::shared_ptr<BoundColumnRefExpression> f3_p_size2_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    Value value_10l(10);
    std::shared_ptr<BoundConstantExpression> right_p_size2_2 = std::make_shared<BoundConstantExpression>(value_10l);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression5_2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f3_p_size2_2, right_p_size2_2);

    Value value_MED1("MED BAG");
    Value value_MED2("MED BOX");
    Value value_MED3("MED PACK");
    Value value_MED4("MED PKG");
    std::vector<Value> value_MED_set = {value_MED1, value_MED2, value_MED3, value_MED4};
    std::shared_ptr<BoundColumnRefExpression> f3_p_container_2 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 7, 0);
    std::shared_ptr<BoundInExpression> f3_inExpression1_2 = std::make_shared<BoundInExpression>(f3_p_container_2, value_MED_set, LogicalType::STRING);

    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression1_2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression2_2, f3_comparisonExpression3_2);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression2_2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression4_2, f3_comparisonExpression5_2);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression3_2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_conjunctionExpression1_2, f3_conjunctionExpression2_2);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression4_2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_conjunctionExpression3_2, f3_inExpression1_2);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression5_2 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression1_2, f3_conjunctionExpression4_2);
    f3_conjunctionExpression5_2->alias = "2";
    std::shared_ptr<BoundColumnRefExpression> f3_p_brand1_3 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    Value value_Brand_34("Brand#34");
    std::shared_ptr<BoundConstantExpression> right_p_brand1_3 = std::make_shared<BoundConstantExpression>(value_Brand_34);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression1_3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f3_p_brand1_3, right_p_brand1_3);

    std::shared_ptr<BoundColumnRefExpression> f3_l_quantity1_3 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    std::shared_ptr<BoundConstantExpression> right_l_quantity1_3 = std::make_shared<BoundConstantExpression>(value_20f);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression2_3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f3_l_quantity1_3, right_l_quantity1_3);

    std::shared_ptr<BoundColumnRefExpression> f3_l_quantity2_3 = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value value_30f(30.0f);
    std::shared_ptr<BoundConstantExpression> right_l_quantity2_3 = std::make_shared<BoundConstantExpression>(value_30f);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression3_3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f3_l_quantity2_3, right_l_quantity2_3);

    std::shared_ptr<BoundColumnRefExpression> f3_p_size1_3 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    std::shared_ptr<BoundConstantExpression> right_p_size1_3 = std::make_shared<BoundConstantExpression>(value_1l);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression4_3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f3_p_size1_3, right_p_size1_3);

    std::shared_ptr<BoundColumnRefExpression> f3_p_size2_3 = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 6, 0);
    Value value_15l(15);
    std::shared_ptr<BoundConstantExpression> right_p_size2_3 = std::make_shared<BoundConstantExpression>(value_15l);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression5_3 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHANOREQUALTO, f3_p_size2_3, right_p_size2_3);

    Value value_LG1("LG CASE");
    Value value_LG2("LG BOX");
    Value value_LG3("LG PACK");
    Value value_LG4("LG PKG");
    std::vector<Value> value_LG_set = {value_LG1, value_LG2, value_LG3, value_LG4};
    std::shared_ptr<BoundColumnRefExpression> f3_p_container_3 = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 7, 0);
    std::shared_ptr<BoundInExpression> f3_inExpression1_3 = std::make_shared<BoundInExpression>(f3_p_container_3, value_LG_set, LogicalType::STRING);

    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression1_3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression2_3, f3_comparisonExpression3_3);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression2_3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression4_3, f3_comparisonExpression5_3);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression3_3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_conjunctionExpression1_3, f3_conjunctionExpression2_3);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression4_3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_conjunctionExpression3_3, f3_inExpression1_3);
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression5_3 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f3_comparisonExpression1_3, f3_conjunctionExpression4_3);
    f3_conjunctionExpression5_3->alias = "3";
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression6 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_OR, f3_conjunctionExpression5, f3_conjunctionExpression5_2);
    f3_conjunctionExpression6->alias = "4";
    std::shared_ptr<BoundConjunctionExpression> f3_conjunctionExpression7 = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_OR, f3_conjunctionExpression6, f3_conjunctionExpression5_3);
    f3_conjunctionExpression7->alias = "5";
    // <l_partkey, l_quantity, l_extendedprice, l_discount, p_partkey, p_brand, p_size, p_container>
    std::shared_ptr<PhysicalFilter> filter3 = std::make_shared<PhysicalFilter>(f3_conjunctionExpression7);
    // std::shared_ptr<PhysicalFilter> filter3 = std::make_shared<PhysicalFilter>(f3_conjunctionExpression5_3);
    filter3->exp_name = "3";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p2_l_extendedprice = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_l_discount = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 3, 0);

    std::vector<LogicalType> p2_arguments1 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p p2_function1 = GetSubFunction();
    ScalarProjectFunction p2_bound_function1("-", p2_arguments1, LogicalType::FLOAT, p2_function1, nullptr);
    std::shared_ptr<BoundConstantExpression> constant1_col = std::make_shared<BoundConstantExpression>(value_1f);
    std::vector<std::shared_ptr<Expression>> p2_expressions1 = {constant1_col, p2_l_discount};
    std::shared_ptr<BoundProjectFunctionExpression> discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p2_bound_function1, p2_expressions1, nullptr);
    discount_1_col->alias = "1-l_discount";

    std::vector<LogicalType> p2_arguments2 = { LogicalType::FLOAT, LogicalType::FLOAT };
    scalar_function_p p2_function2 = GetMulFunction();
    ScalarProjectFunction p2_bound_function2("*", p2_arguments2, LogicalType::FLOAT, p2_function2, nullptr);
    std::vector<std::shared_ptr<Expression>> p2_expressions2 = {p2_l_extendedprice, discount_1_col};
    std::shared_ptr<BoundProjectFunctionExpression> extendedprice_discount_1_col = std::make_shared<BoundProjectFunctionExpression>(LogicalType::FLOAT, p2_bound_function2, p2_expressions2, nullptr);
    extendedprice_discount_1_col->alias = "l_extendedprice * (1 - l_discount)";

    std::vector<std::shared_ptr<Expression>> p2_expressions = {extendedprice_discount_1_col};
    // <l_extendedprice * (1 - l_discount)>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    // ================================================构建HashAgg================================================
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::SUM};
    std::vector<int32_t> group_item_idxs = {0};
    // <Sum(l_extendedprice * (1 - l_discount))>
    std::shared_ptr<PhysicalHashAgg> hashAgg = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, group_item_idxs);


    hashAgg->AddChild(project2);
    project2->AddChild(filter3);
    filter3->AddChild(join1);
    join1->AddChild(scan_part);
    join1->AddChild(project1);
    project1->AddChild(filter2);
    filter2->AddChild(filter1);
    filter1->AddChild(scan_lineitem);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    hashAgg->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q19执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q20=============================
// 测试单线程Q20查询
TEST(TPCHTest, Q20SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    InsertPart(table_part, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Partsupp表数据
    std::shared_ptr<Table> table_partsupp;
    InsertPartsupp(table_partsupp, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertPartsupp Finish!!!", __FILE__, __LINE__);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    InsertNation(table_nation, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    InsertSupplier(table_supplier, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> lineitem_ids = {1,2,4,10};
    // <l_partkey, l_suppkey, l_quantity, l_shipdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> part_ids = {0,1};
    // <p_partkey, p_name>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    std::vector<int> partsupp_ids = {0,1,2};
    // <ps_partkey, ps_suppkey, ps_availqty>
    std::shared_ptr<PhysicalTableScan> scan_partsupp = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);

    std::vector<int> nation_ids = {0,1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> supplier_ids = {0,1,2,3};
    // <s_suppkey, s_name, s_address, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_p_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::string like_pattern = "forest%";
    ScalarFunction bound_function = LikeFun::GetLikeFunction();
    Value value_pattern(like_pattern);
    std::shared_ptr<BoundConstantExpression> right_p_name = std::make_shared<BoundConstantExpression>(value_pattern);
    std::vector<std::shared_ptr<Expression>> arguments = {f1_p_name, right_p_name};
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments, nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);
    // <p_partkey, p_name>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(functionExpression);
    filter1->exp_name = "1";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_p_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_p_partkey};
    // <p_partkey>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids = {0};
    std::vector<int> prode_ids = {0};
    // <ps_partkey, ps_suppkey, ps_availqty>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::SEMI, build_ids, prode_ids);
    join1->exp_name = "1";

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f2_l_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_757353600(757353600);
    std::shared_ptr<BoundConstantExpression> right_l_shipdate = std::make_shared<BoundConstantExpression>(value_757353600);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression1 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f2_l_shipdate, right_l_shipdate);
    Value value_788889600(788889600);
    std::shared_ptr<BoundConstantExpression> right_l_shipdate2 = std::make_shared<BoundConstantExpression>(value_788889600);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN, f2_l_shipdate, right_l_shipdate2);
    std::shared_ptr<BoundConjunctionExpression> f2_conjunctionExpression = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f2_comparisonExpression1, f2_comparisonExpression2);
    // <l_partkey, l_suppkey, l_quantity, l_shipdate>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(f2_conjunctionExpression);
    filter2->exp_name = "2";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p2_l_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_l_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_l_partkey, p2_l_suppkey, p2_l_quantity};
    // <l_partkey, l_suppkey, l_quantity>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    // ================================================构建HashAgg================================================
    // 构建HashAgg
    std::vector<int> group_set = {0,1};
    std::vector<int> agg_set = {2};
    std::vector<int> star_bitmap = {0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM};
    // <l_partkey, l_suppkey, Sum(l_quantity)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg1 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p3_l_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_l_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_sum_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 2, 0);
    Value value_05(0.5);
    std::shared_ptr<BoundConstantExpression> contant05 = std::make_shared<BoundConstantExpression>(value_05);
    std::vector<LogicalType> p3_arguments = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p p3_function = GetMulFunction();
    ScalarProjectFunction p3_bound_function("*", p3_arguments, LogicalType::DOUBLE, p3_function, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions = {contant05, p3_sum_l_quantity};
    std::shared_ptr<BoundProjectFunctionExpression> sum_l_quantity_05 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::DOUBLE, p3_bound_function, p3_expressions, nullptr);
    sum_l_quantity_05->alias = "0.5 * Sum(l_quantity)";
    std::vector<std::shared_ptr<Expression>> p3_expressions2 = {p3_l_partkey, p3_l_suppkey, sum_l_quantity_05};
    // <l_partkey, l_suppkey, 0.5 * Sum(l_quantity)>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions2);
    project3->exp_name = "3";

    std::vector<int> build_ids2 = {0,1};
    std::vector<int> prode_ids2 = {0,1};
    // <ps_partkey, ps_suppkey, ps_availqty, l_partkey, l_suppkey, 0.5 * Sum(l_quantity)>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::LEFT, build_ids2, prode_ids2);
    join2->exp_name = "2";

    std::shared_ptr<BoundColumnRefExpression> f3_ps_availqty = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> f3_05_sum_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 5, 0);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHAN, f3_ps_availqty, f3_05_sum_l_quantity);
    // <ps_partkey, ps_suppkey, ps_availqty, l_partkey, l_suppkey, 0.5 * Sum(l_quantity)>
    std::shared_ptr<PhysicalFilter> filter3 = std::make_shared<PhysicalFilter>(f3_comparisonExpression);
    filter3->exp_name = "3";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p4_ps_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p4_expressions = {p4_ps_suppkey};
    // <ps_suppkey>
    std::shared_ptr<PhysicalProject> project4 = std::make_shared<PhysicalProject>(p4_expressions);
    project4->exp_name = "4";

    std::shared_ptr<BoundColumnRefExpression> f4_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_CANADA("CANADA");
    std::shared_ptr<BoundConstantExpression> right_n_name = std::make_shared<BoundConstantExpression>(value_CANADA);
    std::shared_ptr<BoundComparisonExpression> f4_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f4_n_name, right_n_name);
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalFilter> filter4 = std::make_shared<PhysicalFilter>(f4_comparisonExpression);
    filter4->exp_name = "4";

    std::vector<int> build_ids4 = {0};
    std::vector<int> prode_ids4 = {3};
    // <s_suppkey, s_name, s_address, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join4 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);
    join4->exp_name = "4";

    std::vector<int> build_ids3 = {0};
    std::vector<int> prode_ids3 = {0};
    // <s_suppkey, s_name, s_address, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join3 = std::make_shared<PhysicalHashJoin>(JoinTypes::SEMI, build_ids3, prode_ids3);
    join3->exp_name = "3";

    std::shared_ptr<BoundColumnRefExpression> p5_s_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p5_s_address = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);
    std::vector<std::shared_ptr<Expression>> p5_expressions = {p5_s_name, p5_s_address};
    // <s_name, s_address>
    std::shared_ptr<PhysicalProject> project5 = std::make_shared<PhysicalProject>(p5_expressions);
    project5->exp_name = "5";

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::STRING};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(project5);
    project5->AddChild(join3);
    join3->AddChild(project4);
    join3->AddChild(join4);
    project4->AddChild(filter3);
    filter3->AddChild(join2);
    join2->AddChild(project3);
    join2->AddChild(join1);
    project3->AddChild(hashAgg1);
    hashAgg1->AddChild(project2);
    project2->AddChild(filter2);
    filter2->AddChild(scan_lineitem);
    join1->AddChild(project1);
    join1->AddChild(scan_partsupp);
    project1->AddChild(filter1);
    filter1->AddChild(scan_part);
    join4->AddChild(filter4);
    join4->AddChild(scan_supplier);
    filter4->AddChild(scan_nation);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q20执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q20查询
TEST(TPCHTest, Q20FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    // 插入Part表数据
    std::shared_ptr<Table> table_part;
    std::vector<std::string> part_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "part.tbl_" + std::to_string(i);
        part_file_names.emplace_back(file_name);
    }
    InsertPartMul(table_part, scheduler, work_ids, partition_idxs, part_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertPart Finish!!!", __FILE__, __LINE__);

    // 插入Partsupp表数据
    std::shared_ptr<Table> table_partsupp;
    std::vector<std::string> partsupp_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "partsupp.tbl_" + std::to_string(i);
        partsupp_file_names.emplace_back(file_name);
    }
    InsertPartsuppMul(table_partsupp, scheduler, work_ids, partition_idxs, partsupp_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertPartsupp Finish!!!", __FILE__, __LINE__);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    std::vector<std::string> nation_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "nation.tbl_" + std::to_string(i);
        nation_file_names.emplace_back(file_name);
    }
    InsertNationMul(table_nation, scheduler, work_ids, partition_idxs, nation_file_names);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    std::vector<std::string> supplier_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "supplier.tbl_" + std::to_string(i);
        supplier_file_names.emplace_back(file_name);
    }
    InsertSupplierMul(table_supplier, scheduler, work_ids, partition_idxs, supplier_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> lineitem_ids = {1,2,4,10};
    // <l_partkey, l_suppkey, l_quantity, l_shipdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids);

    std::vector<int> part_ids = {0,1};
    // <p_partkey, p_name>
    std::shared_ptr<PhysicalTableScan> scan_part = std::make_shared<PhysicalTableScan>(table_part, -1, part_ids);

    std::vector<int> partsupp_ids = {0,1,2};
    // <ps_partkey, ps_suppkey, ps_availqty>
    std::shared_ptr<PhysicalTableScan> scan_partsupp = std::make_shared<PhysicalTableScan>(table_partsupp, -1, partsupp_ids);

    std::vector<int> nation_ids = {0,1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> supplier_ids = {0,1,2,3};
    // <s_suppkey, s_name, s_address, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_p_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::string like_pattern = "forest%";
    ScalarFunction bound_function = LikeFun::GetLikeFunction();
    Value value_pattern(like_pattern);
    std::shared_ptr<BoundConstantExpression> right_p_name = std::make_shared<BoundConstantExpression>(value_pattern);
    std::vector<std::shared_ptr<Expression>> arguments = {f1_p_name, right_p_name};
    std::shared_ptr<BoundFunctionExpression> functionExpression = std::make_shared<BoundFunctionExpression>(LogicalType::BOOL, bound_function, arguments, nullptr);
    functionExpression->bind_info = functionExpression->function.bind(functionExpression->function, functionExpression->children);
    // <p_partkey, p_name>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(functionExpression);
    filter1->exp_name = "1";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_p_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_p_partkey};
    // <p_partkey>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids = {0};
    std::vector<int> prode_ids = {0};
    // <ps_partkey, ps_suppkey, ps_availqty>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::SEMI, build_ids, prode_ids);
    join1->exp_name = "1";

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f2_l_shipdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    Value value_757353600(757353600);
    std::shared_ptr<BoundConstantExpression> right_l_shipdate = std::make_shared<BoundConstantExpression>(value_757353600);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression1 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHANOREQUALTO, f2_l_shipdate, right_l_shipdate);
    Value value_788889600(788889600);
    std::shared_ptr<BoundConstantExpression> right_l_shipdate2 = std::make_shared<BoundConstantExpression>(value_788889600);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression2 = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_LESSTHAN, f2_l_shipdate, right_l_shipdate2);
    std::shared_ptr<BoundConjunctionExpression> f2_conjunctionExpression = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f2_comparisonExpression1, f2_comparisonExpression2);
    // <l_partkey, l_suppkey, l_quantity, l_shipdate>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(f2_conjunctionExpression);
    filter2->exp_name = "2";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p2_l_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_l_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_l_partkey, p2_l_suppkey, p2_l_quantity};
    // <l_partkey, l_suppkey, l_quantity>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    // ================================================构建HashAgg================================================
    // 构建HashAgg
    std::vector<int> group_set = {0,1};
    std::vector<int> agg_set = {2};
    std::vector<int> star_bitmap = {0};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::SUM};
    // <l_partkey, l_suppkey, Sum(l_quantity)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg1 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p3_l_partkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_l_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_sum_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 2, 0);
    Value value_05(0.5);
    std::shared_ptr<BoundConstantExpression> contant05 = std::make_shared<BoundConstantExpression>(value_05);
    std::vector<LogicalType> p3_arguments = { LogicalType::DOUBLE, LogicalType::DOUBLE };
    scalar_function_p p3_function = GetMulFunction();
    ScalarProjectFunction p3_bound_function("*", p3_arguments, LogicalType::DOUBLE, p3_function, nullptr);
    std::vector<std::shared_ptr<Expression>> p3_expressions = {contant05, p3_sum_l_quantity};
    std::shared_ptr<BoundProjectFunctionExpression> sum_l_quantity_05 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::DOUBLE, p3_bound_function, p3_expressions, nullptr);
    sum_l_quantity_05->alias = "0.5 * Sum(l_quantity)";
    std::vector<std::shared_ptr<Expression>> p3_expressions2 = {p3_l_partkey, p3_l_suppkey, sum_l_quantity_05};
    // <l_partkey, l_suppkey, 0.5 * Sum(l_quantity)>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions2);
    project3->exp_name = "3";

    std::vector<int> build_ids2 = {0,1};
    std::vector<int> prode_ids2 = {0,1};
    // <ps_partkey, ps_suppkey, ps_availqty, l_partkey, l_suppkey, 0.5 * Sum(l_quantity)>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::LEFT, build_ids2, prode_ids2);
    join2->exp_name = "2";

    std::shared_ptr<BoundColumnRefExpression> f3_ps_availqty = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> f3_05_sum_l_quantity = std::make_shared<BoundColumnRefExpression>(LogicalType::DOUBLE, 0, 5, 0);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHAN, f3_ps_availqty, f3_05_sum_l_quantity);
    // <ps_partkey, ps_suppkey, ps_availqty, l_partkey, l_suppkey, 0.5 * Sum(l_quantity)>
    std::shared_ptr<PhysicalFilter> filter3 = std::make_shared<PhysicalFilter>(f3_comparisonExpression);
    filter3->exp_name = "3";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p4_ps_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p4_expressions = {p4_ps_suppkey};
    // <ps_suppkey>
    std::shared_ptr<PhysicalProject> project4 = std::make_shared<PhysicalProject>(p4_expressions);
    project4->exp_name = "4";

    std::shared_ptr<BoundColumnRefExpression> f4_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_CANADA("CANADA");
    std::shared_ptr<BoundConstantExpression> right_n_name = std::make_shared<BoundConstantExpression>(value_CANADA);
    std::shared_ptr<BoundComparisonExpression> f4_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f4_n_name, right_n_name);
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalFilter> filter4 = std::make_shared<PhysicalFilter>(f4_comparisonExpression);
    filter4->exp_name = "4";

    std::vector<int> build_ids4 = {0};
    std::vector<int> prode_ids4 = {3};
    // <s_suppkey, s_name, s_address, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join4 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids4, prode_ids4);
    join4->exp_name = "4";

    std::vector<int> build_ids3 = {0};
    std::vector<int> prode_ids3 = {0};
    // <s_suppkey, s_name, s_address, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join3 = std::make_shared<PhysicalHashJoin>(JoinTypes::SEMI, build_ids3, prode_ids3);
    join3->exp_name = "3";

    std::shared_ptr<BoundColumnRefExpression> p5_s_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p5_s_address = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 2, 0);
    std::vector<std::shared_ptr<Expression>> p5_expressions = {p5_s_name, p5_s_address};
    // <s_name, s_address>
    std::shared_ptr<PhysicalProject> project5 = std::make_shared<PhysicalProject>(p5_expressions);
    project5->exp_name = "5";

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::STRING};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(project5);
    project5->AddChild(join3);
    join3->AddChild(project4);
    join3->AddChild(join4);
    project4->AddChild(filter3);
    filter3->AddChild(join2);
    join2->AddChild(project3);
    join2->AddChild(join1);
    project3->AddChild(hashAgg1);
    hashAgg1->AddChild(project2);
    project2->AddChild(filter2);
    filter2->AddChild(scan_lineitem);
    join1->AddChild(project1);
    join1->AddChild(scan_partsupp);
    project1->AddChild(filter1);
    filter1->AddChild(scan_part);
    join4->AddChild(filter4);
    join4->AddChild(scan_supplier);
    filter4->AddChild(scan_nation);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q20执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q21=============================
// 测试单线程Q21查询
TEST(TPCHTest, Q21SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    InsertLineitem(table_lineitem, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    InsertNation(table_nation, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    InsertSupplier(table_supplier, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    InsertOrders(table_orders, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> lineitem_ids1 = {0,2,11,12};
    // <l_orderkey, l_suppkey, l_commitdate, l_receiptdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem1 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids1);

    std::vector<int> lineitem_ids2 = {0,2};
    // <l_orderkey, l_suppkey>
    std::shared_ptr<PhysicalTableScan> scan_lineitem2 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids2);

    std::vector<int> lineitem_ids3 = {0,2,11,12};
    // <l_orderkey, l_suppkey, l_commitdate, l_receiptdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem3 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids3);

    std::vector<int> nation_ids = {0,1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> supplier_ids = {0,1,3};
    // <s_suppkey, s_name, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    std::vector<int> orders_ids = {0,2};
    // <o_orderkey, o_orderstatus>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_pattern("SAUDI ARABIA");
    std::shared_ptr<BoundConstantExpression> right_n_name = std::make_shared<BoundConstantExpression>(value_pattern);
    std::shared_ptr<BoundComparisonExpression> f1_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f1_n_name, right_n_name);
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(f1_comparisonExpression);
    filter1->exp_name = "1";

    std::shared_ptr<BoundColumnRefExpression> f2_l_receiptdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> f2_l_commitdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHAN, f2_l_receiptdate, f2_l_commitdate);
    // <l_orderkey, l_suppkey, l_commitdate, l_receiptdate>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(f2_comparisonExpression);
    filter2->exp_name = "2";

    std::shared_ptr<BoundColumnRefExpression> f3_o_orderstatus = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_F("F");
    std::shared_ptr<BoundConstantExpression> right_o_orderstatus = std::make_shared<BoundConstantExpression>(value_F);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f3_o_orderstatus, right_o_orderstatus);
    // <o_orderkey, o_orderstatus>
    std::shared_ptr<PhysicalFilter> filter3 = std::make_shared<PhysicalFilter>(f3_comparisonExpression);
    filter3->exp_name = "3";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_l_orderkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_l_orderkey, p1_l_suppkey};
    // <l_orderkey, l_suppkey>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids = {0};
    std::vector<int> prode_ids = {2};
    // <s_suppkey, s_name, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids, prode_ids);
    join1->exp_name = "1";

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {1};
    // <l_orderkey, l_suppkey, s_suppkey, s_name, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join2->exp_name = "2";

    std::vector<int> build_ids3 = {0};
    std::vector<int> prode_ids3 = {0};
    // <o_orderkey, o_orderstatus, l_orderkey, l_suppkey, s_suppkey, s_name, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join3 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    join3->exp_name = "3";

    // TODO: 支持!=比较
    std::vector<int> build_ids4 = {0,1};
    std::vector<int> prode_ids4 = {2,3};
    std::vector<ExpressionTypes> types = {ExpressionTypes::COMPARE_EQUAL, ExpressionTypes::COMPARE_NOTEQUAL};
    // <o_orderkey, o_orderstatus, l_orderkey, l_suppkey, s_suppkey, s_name, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join4 = std::make_shared<PhysicalHashJoin>(JoinTypes::SEMI, build_ids4, prode_ids4, types);
    join4->exp_name = "4";

    std::shared_ptr<BoundColumnRefExpression> f4_l_receiptdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> f4_l_commitdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::shared_ptr<BoundComparisonExpression> f4_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHAN, f4_l_receiptdate, f4_l_commitdate);
    // <l_orderkey, l_suppkey, l_commitdate, l_receiptdate>
    std::shared_ptr<PhysicalFilter> filter4 = std::make_shared<PhysicalFilter>(f4_comparisonExpression);
    filter4->exp_name = "4";

    std::shared_ptr<BoundColumnRefExpression> p2_l_orderkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_l_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_l_orderkey, p2_l_suppkey};
    // <l_orderkey, l_suppkey>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    std::vector<int> build_ids5 = {0,1};
    std::vector<int> prode_ids5 = {2,3};
    // <o_orderkey, o_orderstatus, l_orderkey, l_suppkey, s_suppkey, s_name, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join5 = std::make_shared<PhysicalHashJoin>(JoinTypes::ANTI, build_ids5, prode_ids5, types);
    join5->exp_name = "5";

    std::shared_ptr<BoundColumnRefExpression> p3_s_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    std::vector<std::shared_ptr<Expression>> p3_expressions = {p3_s_name};
    // <s_name>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions);
    project3->exp_name = "3";

    // ================================================构建HashAgg================================================
    // 构建HashAgg
    std::vector<int> group_set = {0};
    std::vector<int> agg_set = {0};
    std::vector<int> star_bitmap = {1};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::COUNT};
    // <s_name, Count(*)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg1 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {1, 0};
    std::vector<LogicalType> key_types = {LogicalType::INTEGER, LogicalType::STRING};
    std::vector<SortOrder> orders_p = {SortOrder::DESCENDING, SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg1);
    hashAgg1->AddChild(project3);
    project3->AddChild(join5);
    join5->AddChild(project2);
    project2->AddChild(filter4);
    filter4->AddChild(scan_lineitem3);
    join5->AddChild(join4);
    join4->AddChild(scan_lineitem2);
    join4->AddChild(join3);
    join3->AddChild(join2);
    join3->AddChild(filter3);
    filter3->AddChild(scan_orders);
    join2->AddChild(join1);
    join2->AddChild(project1);
    project1->AddChild(filter2);
    filter2->AddChild(scan_lineitem1);
    join1->AddChild(filter1);
    join1->AddChild(scan_supplier);
    filter1->AddChild(scan_nation);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q21执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q21查询
TEST(TPCHTest, Q21FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Lineitem表数据
    std::shared_ptr<Table> table_lineitem;
    std::vector<std::string> lineitem_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "lineitem.tbl_" + std::to_string(i);
        lineitem_file_names.emplace_back(file_name);
    }
    InsertLineitemMul(table_lineitem, scheduler, work_ids, partition_idxs, lineitem_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertLineitem Finish!!!", __FILE__, __LINE__);

    // 插入Nation表数据
    std::shared_ptr<Table> table_nation;
    std::vector<std::string> nation_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "nation.tbl_" + std::to_string(i);
        nation_file_names.emplace_back(file_name);
    }
    InsertNationMul(table_nation, scheduler, work_ids, partition_idxs, nation_file_names);
    importFinish = false;
    spdlog::info("[{} : {}] InsertNation Finish!!!", __FILE__, __LINE__);

    // 插入Supplier表数据
    std::shared_ptr<Table> table_supplier;
    std::vector<std::string> supplier_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "supplier.tbl_" + std::to_string(i);
        supplier_file_names.emplace_back(file_name);
    }
    InsertSupplierMul(table_supplier, scheduler, work_ids, partition_idxs, supplier_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertSupplier Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> lineitem_ids1 = {0,2,11,12};
    // <l_orderkey, l_suppkey, l_commitdate, l_receiptdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem1 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids1);

    std::vector<int> lineitem_ids2 = {0,2};
    // <l_orderkey, l_suppkey>
    std::shared_ptr<PhysicalTableScan> scan_lineitem2 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids2);

    std::vector<int> lineitem_ids3 = {0,2,11,12};
    // <l_orderkey, l_suppkey, l_commitdate, l_receiptdate>
    std::shared_ptr<PhysicalTableScan> scan_lineitem3 = std::make_shared<PhysicalTableScan>(table_lineitem, -1, lineitem_ids3);

    std::vector<int> nation_ids = {0,1};
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalTableScan> scan_nation = std::make_shared<PhysicalTableScan>(table_nation, -1, nation_ids);

    std::vector<int> supplier_ids = {0,1,3};
    // <s_suppkey, s_name, s_nationkey>
    std::shared_ptr<PhysicalTableScan> scan_supplier = std::make_shared<PhysicalTableScan>(table_supplier, -1, supplier_ids);

    std::vector<int> orders_ids = {0,2};
    // <o_orderkey, o_orderstatus>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_n_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_pattern("SAUDI ARABIA");
    std::shared_ptr<BoundConstantExpression> right_n_name = std::make_shared<BoundConstantExpression>(value_pattern);
    std::shared_ptr<BoundComparisonExpression> f1_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f1_n_name, right_n_name);
    // <n_nationkey, n_name>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(f1_comparisonExpression);
    filter1->exp_name = "1";

    std::shared_ptr<BoundColumnRefExpression> f2_l_receiptdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> f2_l_commitdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::shared_ptr<BoundComparisonExpression> f2_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHAN, f2_l_receiptdate, f2_l_commitdate);
    // <l_orderkey, l_suppkey, l_commitdate, l_receiptdate>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(f2_comparisonExpression);
    filter2->exp_name = "2";

    std::shared_ptr<BoundColumnRefExpression> f3_o_orderstatus = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_F("F");
    std::shared_ptr<BoundConstantExpression> right_o_orderstatus = std::make_shared<BoundConstantExpression>(value_F);
    std::shared_ptr<BoundComparisonExpression> f3_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_EQUAL, f3_o_orderstatus, right_o_orderstatus);
    // <o_orderkey, o_orderstatus>
    std::shared_ptr<PhysicalFilter> filter3 = std::make_shared<PhysicalFilter>(f3_comparisonExpression);
    filter3->exp_name = "3";

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_l_orderkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_l_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_l_orderkey, p1_l_suppkey};
    // <l_orderkey, l_suppkey>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建HashJoin================================================
    std::vector<int> build_ids = {0};
    std::vector<int> prode_ids = {2};
    // <s_suppkey, s_name, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join1 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids, prode_ids);
    join1->exp_name = "1";

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {1};
    // <l_orderkey, l_suppkey, s_suppkey, s_name, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids2, prode_ids2);
    join2->exp_name = "2";

    std::vector<int> build_ids3 = {0};
    std::vector<int> prode_ids3 = {0};
    // <o_orderkey, o_orderstatus, l_orderkey, l_suppkey, s_suppkey, s_name, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join3 = std::make_shared<PhysicalHashJoin>(JoinTypes::INNER, build_ids3, prode_ids3);
    join3->exp_name = "3";

    // TODO: 支持!=比较
    std::vector<int> build_ids4 = {0,1};
    std::vector<int> prode_ids4 = {2,3};
    std::vector<ExpressionTypes> types = {ExpressionTypes::COMPARE_EQUAL, ExpressionTypes::COMPARE_NOTEQUAL};
    // <o_orderkey, o_orderstatus, l_orderkey, l_suppkey, s_suppkey, s_name, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join4 = std::make_shared<PhysicalHashJoin>(JoinTypes::SEMI, build_ids4, prode_ids4, types);
    join4->exp_name = "4";

    std::shared_ptr<BoundColumnRefExpression> f4_l_receiptdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 3, 0);
    std::shared_ptr<BoundColumnRefExpression> f4_l_commitdate = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 2, 0);
    std::shared_ptr<BoundComparisonExpression> f4_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHAN, f4_l_receiptdate, f4_l_commitdate);
    // <l_orderkey, l_suppkey, l_commitdate, l_receiptdate>
    std::shared_ptr<PhysicalFilter> filter4 = std::make_shared<PhysicalFilter>(f4_comparisonExpression);
    filter4->exp_name = "4";

    std::shared_ptr<BoundColumnRefExpression> p2_l_orderkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p2_l_suppkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_l_orderkey, p2_l_suppkey};
    // <l_orderkey, l_suppkey>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    std::vector<int> build_ids5 = {0,1};
    std::vector<int> prode_ids5 = {2,3};
    // <o_orderkey, o_orderstatus, l_orderkey, l_suppkey, s_suppkey, s_name, s_nationkey, n_nationkey, n_name>
    std::shared_ptr<PhysicalHashJoin> join5 = std::make_shared<PhysicalHashJoin>(JoinTypes::ANTI, build_ids5, prode_ids5, types);
    join5->exp_name = "5";

    std::shared_ptr<BoundColumnRefExpression> p3_s_name = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 5, 0);
    std::vector<std::shared_ptr<Expression>> p3_expressions = {p3_s_name};
    // <s_name>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions);
    project3->exp_name = "3";

    // ================================================构建HashAgg================================================
    // 构建HashAgg
    std::vector<int> group_set = {0};
    std::vector<int> agg_set = {0};
    std::vector<int> star_bitmap = {1};
    std::vector<AggFunctionType> aggregate_function_types = {AggFunctionType::COUNT};
    // <s_name, Count(*)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg1 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set, agg_set, star_bitmap, aggregate_function_types);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::STRING};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg1);
    hashAgg1->AddChild(project3);
    project3->AddChild(join5);
    join5->AddChild(project2);
    project2->AddChild(filter4);
    filter4->AddChild(scan_lineitem3);
    join5->AddChild(join4);
    join4->AddChild(scan_lineitem2);
    join4->AddChild(join3);
    join3->AddChild(join2);
    join3->AddChild(filter3);
    filter3->AddChild(scan_orders);
    join2->AddChild(join1);
    join2->AddChild(project1);
    project1->AddChild(filter2);
    filter2->AddChild(scan_lineitem1);
    join1->AddChild(filter1);
    join1->AddChild(scan_supplier);
    filter1->AddChild(scan_nation);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q22执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// =============================Q22=============================
// 测试单线程Q22查询
TEST(TPCHTest, Q22SingleThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);

    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    InsertCustomer(table_customer, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    InsertOrders(table_orders, scheduler);
    importFinish = false;
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> customer_ids = {4, 5};
    // <c_phone, c_acctbal>
    std::shared_ptr<PhysicalTableScan> scan_customer1 = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> customer_ids2 = {0, 4, 5};
    // <c_custkey, c_phone, c_acctbal>
    std::shared_ptr<PhysicalTableScan> scan_customer2 = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids2);

    std::vector<int> orders_ids = {1};
    // <o_custkey>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_c_phone = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value val_start(0);
    std::shared_ptr<BoundConstantExpression> start_pos = std::make_shared<BoundConstantExpression>(val_start);
    Value val_len(2);
    std::shared_ptr<BoundConstantExpression> len = std::make_shared<BoundConstantExpression>(val_len);

    ScalarProjectFunction bound_function = SubStringFun::GetSubStringFunction();
    std::vector<std::shared_ptr<Expression>> func_arguments = {start_pos, len};
    std::vector<std::shared_ptr<Expression>> arguments = {p1_c_phone, p1_c_phone};
    std::shared_ptr<BoundProjectFunctionExpression> expr1 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::STRING, bound_function, arguments, nullptr);
    expr1->bind_info = expr1->function.bind(expr1->function, func_arguments);
    expr1->alias = "cntrycode";

    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_c_acctbal, expr1};
    // <c_acctbal, cntrycode>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> f1_cntrycode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_0(0.0F);
    std::shared_ptr<BoundConstantExpression> right_c_acctbal = std::make_shared<BoundConstantExpression>(value_0);
    std::shared_ptr<BoundComparisonExpression> f1_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHAN, f1_c_acctbal, right_c_acctbal);
    std::vector<Value> value_set = {Value("13"), Value("31"), Value("23"), Value("30"), Value("18"), Value("17")};
    std::shared_ptr<BoundInExpression> f1_inExpression = std::make_shared<BoundInExpression>(f1_cntrycode, value_set, LogicalType::STRING);
    std::shared_ptr<BoundConjunctionExpression> f1_conjunctionExpression = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f1_comparisonExpression, f1_inExpression);
    // <c_acctbal, cntrycode>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(f1_conjunctionExpression);
    filter1->exp_name = "1";

    std::shared_ptr<BoundColumnRefExpression> p2_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 0, 0);
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_c_acctbal};
    // <c_acctbal>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    //  ================================================构建HashAgg================================================
    std::vector<int> group_item_idxs = {0};
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::AVG };
    // <Avg(c_acctbal)>
    std::shared_ptr<PhysicalHashAgg> hashAgg1 = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, group_item_idxs);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p3_c_phone = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);

    ScalarProjectFunction p3_bound_function = SubStringFun::GetSubStringFunction();
    std::vector<std::shared_ptr<Expression>> p3_func_arguments = {start_pos, len};
    std::vector<std::shared_ptr<Expression>> p3_arguments = {p3_c_phone, p3_c_phone};
    std::shared_ptr<BoundProjectFunctionExpression> p3_expr1 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::STRING, p3_bound_function, p3_arguments, nullptr);
    p3_expr1->bind_info = p3_expr1->function.bind(p3_expr1->function, p3_func_arguments);
    p3_expr1->alias = "cntrycode";

    std::vector<std::shared_ptr<Expression>> p3_expressions = {p3_c_custkey, p3_expr1, p3_c_acctbal};
    // <c_custkey, cntrycode, c_acctbal>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions);
    project1->exp_name = "1";

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f2_cntrycode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundInExpression> f2_inExpression = std::make_shared<BoundInExpression>(f2_cntrycode, value_set, LogicalType::STRING);
    // <c_custkey, cntrycode, c_acctbal>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(f2_inExpression);
    filter2->exp_name = "2";

    //  ================================================构建NestedLoopJoin================================================
    std::vector<int> build_ids = {0};
    std::vector<int> prode_ids = {2};
    std::vector<ExpressionTypes> compare_types = {ExpressionTypes::COMPARE_GREATERTHAN};
    // <c_custkey, cntrycode, c_acctbal, Avg(c_acctbal)>
    std::shared_ptr<PhysicalNestedLoopJoin> join1 = std::make_shared<PhysicalNestedLoopJoin>(JoinTypes::INNER, build_ids, prode_ids, compare_types);
    join1->exp_name = "1";

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {0};
    // <c_custkey, cntrycode, c_acctbal, Avg(c_acctbal)>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::ANTI, build_ids2, prode_ids2);
    join2->exp_name = "2";

    std::shared_ptr<BoundColumnRefExpression> p4_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p4_cntrycode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p4_expressions = {p4_c_acctbal, p4_cntrycode};
    // <c_acctbal, cntrycode>
    std::shared_ptr<PhysicalProject> project4 = std::make_shared<PhysicalProject>(p4_expressions);
    project4->exp_name = "4";

    // ================================================构建HashAgg================================================
    // 构建HashAgg
    std::vector<int> group_set2 = {1};
    std::vector<int> agg_set2 = {0, 0};
    std::vector<int> star_bitmap2 = {1, 0};
    std::vector<AggFunctionType> aggregate_function_types2 = {AggFunctionType::COUNT, AggFunctionType::SUM};
    // <cntrycode, Count(*), Sum(c_acctbal)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg2 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set2, agg_set2, star_bitmap2, aggregate_function_types2);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::STRING};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg2);
    hashAgg2->AddChild(project4);
    project4->AddChild(join2);
    join2->AddChild(scan_orders);
    join2->AddChild(join1);
    join1->AddChild(hashAgg1);
    join1->AddChild(filter2);
    hashAgg1->AddChild(project2);
    project2->AddChild(filter1);
    filter1->AddChild(project1);
    project1->AddChild(scan_customer1);
    filter2->AddChild(project3);
    project3->AddChild(scan_customer2);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q22执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

// 测试4线程Q22查询
TEST(TPCHTest, Q22FourThreadTest) {
    std::shared_ptr<Scheduler> scheduler = std::make_shared<Scheduler>(72);
    std::vector<int> work_ids = {1, 2, 3 ,4};
    std::vector<int> partition_idxs = {1, 2, 3 ,4};
    // 插入Customer表数据
    std::shared_ptr<Table> table_customer;
    std::vector<std::string> customer_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "customer.tbl_" + std::to_string(i);
        customer_file_names.emplace_back(file_name);
    }
    InsertCustomerMul(table_customer, scheduler, work_ids, partition_idxs, customer_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    spdlog::info("[{} : {}] InsertCustomer Finish!!!", __FILE__, __LINE__);

    // 插入Orders表数据
    std::shared_ptr<Table> table_orders;
    std::vector<std::string> orders_file_names;
    for(int i = 0; i < work_ids.size(); i++) {
        std::string file_name = fileDir4 + "/" + "orders.tbl_" + std::to_string(i);
        orders_file_names.emplace_back(file_name);
    }
    InsertOrdersMul(table_orders, scheduler, work_ids, partition_idxs, orders_file_names);
    importFinish = false;
    std::this_thread::sleep_for(std::chrono::seconds(2));
    spdlog::info("[{} : {}] InsertOrders Finish!!!", __FILE__, __LINE__);

    //  ================================================构建Scan================================================
    std::vector<int> customer_ids = {4, 5};
    // <c_phone, c_acctbal>
    std::shared_ptr<PhysicalTableScan> scan_customer1 = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids);

    std::vector<int> customer_ids2 = {0, 4, 5};
    // <c_custkey, c_phone, c_acctbal>
    std::shared_ptr<PhysicalTableScan> scan_customer2 = std::make_shared<PhysicalTableScan>(table_customer, -1, customer_ids2);

    std::vector<int> orders_ids = {1};
    // <o_custkey>
    std::shared_ptr<PhysicalTableScan> scan_orders = std::make_shared<PhysicalTableScan>(table_orders, -1, orders_ids);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p1_c_phone = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> p1_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 1, 0);
    Value val_start(0);
    std::shared_ptr<BoundConstantExpression> start_pos = std::make_shared<BoundConstantExpression>(val_start);
    Value val_len(2);
    std::shared_ptr<BoundConstantExpression> len = std::make_shared<BoundConstantExpression>(val_len);

    ScalarProjectFunction bound_function = SubStringFun::GetSubStringFunction();
    std::vector<std::shared_ptr<Expression>> func_arguments = {start_pos, len};
    std::vector<std::shared_ptr<Expression>> arguments = {p1_c_phone, p1_c_phone};
    std::shared_ptr<BoundProjectFunctionExpression> expr1 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::STRING, bound_function, arguments, nullptr);
    expr1->bind_info = expr1->function.bind(expr1->function, func_arguments);
    expr1->alias = "cntrycode";

    std::vector<std::shared_ptr<Expression>> p1_expressions = {p1_c_acctbal, expr1};
    // <c_acctbal, cntrycode>
    std::shared_ptr<PhysicalProject> project1 = std::make_shared<PhysicalProject>(p1_expressions);
    project1->exp_name = "1";

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f1_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 0, 0);
    std::shared_ptr<BoundColumnRefExpression> f1_cntrycode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    Value value_0(0.0F);
    std::shared_ptr<BoundConstantExpression> right_c_acctbal = std::make_shared<BoundConstantExpression>(value_0);
    std::shared_ptr<BoundComparisonExpression> f1_comparisonExpression = std::make_shared<BoundComparisonExpression>(ExpressionTypes::COMPARE_GREATERTHAN, f1_c_acctbal, right_c_acctbal);
    std::vector<Value> value_set = {Value("13"), Value("31"), Value("23"), Value("30"), Value("18"), Value("17")};
    std::shared_ptr<BoundInExpression> f1_inExpression = std::make_shared<BoundInExpression>(f1_cntrycode, value_set, LogicalType::STRING);
    std::shared_ptr<BoundConjunctionExpression> f1_conjunctionExpression = std::make_shared<BoundConjunctionExpression>(ExpressionTypes::CONJUNCTION_AND, f1_comparisonExpression, f1_inExpression);
    // <c_acctbal, cntrycode>
    std::shared_ptr<PhysicalFilter> filter1 = std::make_shared<PhysicalFilter>(f1_conjunctionExpression);
    filter1->exp_name = "1";

    std::shared_ptr<BoundColumnRefExpression> p2_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 0, 0);
    std::vector<std::shared_ptr<Expression>> p2_expressions = {p2_c_acctbal};
    // <c_acctbal>
    std::shared_ptr<PhysicalProject> project2 = std::make_shared<PhysicalProject>(p2_expressions);
    project2->exp_name = "2";

    //  ================================================构建HashAgg================================================
    std::vector<int> group_item_idxs = {0};
    std::vector<AggFunctionType> aggregate_function_types = { AggFunctionType::AVG };
    // <Avg(c_acctbal)>
    std::shared_ptr<PhysicalHashAgg> hashAgg1 = std::make_shared<PhysicalHashAgg>(-1, aggregate_function_types, group_item_idxs);

    //  ================================================构建Project================================================
    std::shared_ptr<BoundColumnRefExpression> p3_c_phone = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p3_c_custkey = std::make_shared<BoundColumnRefExpression>(LogicalType::INTEGER, 0, 0, 0);

    ScalarProjectFunction p3_bound_function = SubStringFun::GetSubStringFunction();
    std::vector<std::shared_ptr<Expression>> p3_func_arguments = {start_pos, len};
    std::vector<std::shared_ptr<Expression>> p3_arguments = {p3_c_phone, p3_c_phone};
    std::shared_ptr<BoundProjectFunctionExpression> p3_expr1 = std::make_shared<BoundProjectFunctionExpression>(LogicalType::STRING, p3_bound_function, p3_arguments, nullptr);
    p3_expr1->bind_info = p3_expr1->function.bind(p3_expr1->function, p3_func_arguments);
    p3_expr1->alias = "cntrycode";

    std::vector<std::shared_ptr<Expression>> p3_expressions = {p3_c_custkey, p3_expr1, p3_c_acctbal};
    // <c_custkey, cntrycode, c_acctbal>
    std::shared_ptr<PhysicalProject> project3 = std::make_shared<PhysicalProject>(p3_expressions);
    project1->exp_name = "1";

    //  ================================================构建Filter================================================
    std::shared_ptr<BoundColumnRefExpression> f2_cntrycode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::shared_ptr<BoundInExpression> f2_inExpression = std::make_shared<BoundInExpression>(f2_cntrycode, value_set, LogicalType::STRING);
    // <c_custkey, cntrycode, c_acctbal>
    std::shared_ptr<PhysicalFilter> filter2 = std::make_shared<PhysicalFilter>(f2_inExpression);
    filter2->exp_name = "2";

    //  ================================================构建NestedLoopJoin================================================
    std::vector<int> build_ids = {0};
    std::vector<int> prode_ids = {2};
    std::vector<ExpressionTypes> compare_types = {ExpressionTypes::COMPARE_GREATERTHAN};
    // <c_custkey, cntrycode, c_acctbal, Avg(c_acctbal)>
    std::shared_ptr<PhysicalNestedLoopJoin> join1 = std::make_shared<PhysicalNestedLoopJoin>(JoinTypes::INNER, build_ids, prode_ids, compare_types);
    join1->exp_name = "1";

    std::vector<int> build_ids2 = {0};
    std::vector<int> prode_ids2 = {0};
    // <c_custkey, cntrycode, c_acctbal, Avg(c_acctbal)>
    std::shared_ptr<PhysicalHashJoin> join2 = std::make_shared<PhysicalHashJoin>(JoinTypes::ANTI, build_ids2, prode_ids2);
    join2->exp_name = "2";

    std::shared_ptr<BoundColumnRefExpression> p4_c_acctbal = std::make_shared<BoundColumnRefExpression>(LogicalType::FLOAT, 0, 2, 0);
    std::shared_ptr<BoundColumnRefExpression> p4_cntrycode = std::make_shared<BoundColumnRefExpression>(LogicalType::STRING, 0, 1, 0);
    std::vector<std::shared_ptr<Expression>> p4_expressions = {p4_c_acctbal, p4_cntrycode};
    // <c_acctbal, cntrycode>
    std::shared_ptr<PhysicalProject> project4 = std::make_shared<PhysicalProject>(p4_expressions);
    project4->exp_name = "4";

    // ================================================构建HashAgg================================================
    // 构建HashAgg
    std::vector<int> group_set2 = {1};
    std::vector<int> agg_set2 = {0, 0};
    std::vector<int> star_bitmap2 = {1, 0};
    std::vector<AggFunctionType> aggregate_function_types2 = {AggFunctionType::COUNT, AggFunctionType::SUM};
    // <cntrycode, Count(*), Sum(c_acctbal)>
    std::shared_ptr<PhysicalMultiFieldHashAgg> hashAgg2 = std::make_shared<PhysicalMultiFieldHashAgg>(group_set2, agg_set2, star_bitmap2, aggregate_function_types2);

    //  ================================================构建OrderBy================================================
    std::vector<int> sort_keys = {0};
    std::vector<LogicalType> key_types = {LogicalType::STRING};
    std::vector<SortOrder> orders_p = {SortOrder::ASCENDING};
    std::shared_ptr<PhysicalOrder> orderby = std::make_shared<PhysicalOrder>(&sort_keys, &key_types, &orders_p);

    orderby->AddChild(hashAgg2);
    hashAgg2->AddChild(project4);
    project4->AddChild(join2);
    join2->AddChild(scan_orders);
    join2->AddChild(join1);
    join1->AddChild(hashAgg1);
    join1->AddChild(filter2);
    hashAgg1->AddChild(project2);
    project2->AddChild(filter1);
    filter1->AddChild(project1);
    project1->AddChild(scan_customer1);
    filter2->AddChild(project3);
    project3->AddChild(scan_customer2);

    std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>();
    std::shared_ptr<PipelineGroup> pipeline_group = std::make_shared<PipelineGroup>();
    orderby->build_pipelines(pipeline, pipeline_group);
    std::shared_ptr<PipelineGroupExecute> pipeline_group_executor = std::make_shared<PipelineGroupExecute>(scheduler, pipeline_group);
    pipeline_group_executor->traverse_plan();
    auto start_execute = std::chrono::steady_clock::now();
    pipeline_group_executor->execute();
    auto end_execute = std::chrono::steady_clock::now();
    spdlog::info("[{} : {}] Q21执行时间: {}", __FILE__, __LINE__, Util::time_difference(start_execute, end_execute));

    // 关闭线程池
    scheduler->shutdown();
    RC expected = RC::SUCCESS;
    ASSERT_EQ(expected, RC::SUCCESS);
}

